Dziedziczenie klas abstrakcyjnych

 

Klasy abstrakcyjne mogą dziedziczyć od innych klas nie-abstrakcyjnych oraz od klas abstrakcyjnych tak, jak zwykłe klasy. Nie ma ograniczenia liczby poziomów dziedziczenia w drzewie hierarchii dziedziczenia klas abstrakcyjnych.

W klasie abstrakcyjnej dziedziczącej od innej klasy abstrakcyjnej nie muszą występować metody abstrakcyjne zadeklarowane w klasie nadrzędnej (klasie przodka), jeśli na danym poziomie abstrakcji nie są one implementowane. Te metody abstrakcyjne będą musiały być zaimplementowane w klasie potomnej, nie-abstrakcyjnej, która będzie znajdować się na końcu łańcucha dziedziczących od siebie klas abstrakcyjnych.

 

Przykład dziedziczenia klas abstrakcyjnych - bardziej zaawansowany:

Kolor BŁĘKITNY - klasy realnych obiektów (nie-abstrakcyjne);

Kolor ZIELONY - klasy abstrakcyjne;

Kolor FIOLETOWY - interfejsy

Aby wyświetlić diagram w pełnej rozdzielczości w osobnej karcie, kliknij tutaj: _img/Vehicles_UML_model_abstract_class_inheritance_01.png

Odpowiadający temu modelowi kod w języku Java:

// Pojazd kołowy - realna klasa, implementująca wszystkie metody wspólne dla każdego pojazdu na kołach.

public class WheeledVehicle
{
	public String name;
	public int currentSpeed;    // bieżąca prędkość

       // Tocz się na kołach
	public void rollOnWheels( int speed ) {
		// tutaj implementacja procesu toczenia z określoną prędkością
	}
	
       // Zahamuj
	public void brake() {
		// tutaj implementacja procesu hamowania do zatrzymania
	}

}

// Skręcający pojazd kołowy - w tej klasie wys†ępuje metoda turn() realizująca zakręcanie pojazdu. Ale w różnych pojazdach proces 
// zakręcania przebiega różnie i dlatego ta metoda i klasa musi być abstrakcyjna. Inaczej skręca pojazd ze skrętnymi przednimi 
// kołami, inaczej pojazd ze skrętnymi tylnymi, a jeszcze inaczej pojazd z przebugem między przednią a tylną osią.  

public abstract class TurningWheeledVahicle extends WheeledVehicle
{
	public int movingDirection;    // Kierunek poruszania się pojazdu
	
	public abstract void turn( int angle ) ;
}

// Silnikowy pojazd kołowy - w naszym schemacie dziedziczy od skręcającego pojazdu kołowego

public abstract class WheeledMotorVehicle extends TurningWheeledVahicle
{
	public int engineElectricalSystemVoltage;    // napięcie w układzie elektrycznym silnika	
	public int engineRotationSpeed;    // bieżąca prędkość obrotowa silnika


	// Ustaw określone obroty silnika - ten proces przebiega zupełnie inaczej w silnikach spalinowych, 
       // a inaczej w silinikach elektrycznych. Dlatego ta metoda jest abstrakcyjna.

	public abstract void setEngineRotationSpeed( int targetEngineRotationSpeed ) ;

	public void turnEngineOff() {
		// Tutaj implementacja procesu wyłączenia silnika - odcięcie prądu w układzie elektrycznym silnika
	}

}

// Kołowy pojazd elektyczny - w tej klasie znajduje się tylko jedna metoda nie-abstrakcyjna z implementacją. Jest to metoda
// wspólna dla wszystkich pojazdów elektrycznych i kołowych. Jednakże nie ma tutaj implementacji abstrakcyjnych metod 
// zadeklarowanych w klasach nadrzędnych i dlatego ta klasa również musi być abstrakcyjna.

public abstract class WheeledElectricVehicle extends WheeledMotorVehicle
{
	public void setEngineRotationSpeed( int targetEngineRotationSpeed ) {
		// Tutaj implementacja procesu ustawiania określonych obrotów silnika elektrycznego
              // Zwiększamy lub zmniejszamy napięcie, aż silnik osiągnie zadane obroty.  
	}

}

// Interfejs definiujący metody zakręcania używane w pojazdach ze skrętnymi przednimi kołami.

public  interface FrontWheelsTurningVehicle 
{

	public void turn( int angle ) ;
	public void turnFrontWheels( int targetAngle ) ;


}

// Klasa dziedzicząca od wszystkich nadrzędnych klas abstrakcyjnych i nie-abstrakcyjnych a ponadto implementująca interfejs 
// FrontWheelsTurningVehicle. Tutaj implementowane są wszystkie metody zadeklarowane i nie zaimplementowane w nadrzędnych
// klasach abstrakcyjnych oraz w implementowanym interfejsie.

public class ElectricCar extends WheeledElectricVehicle implements FrontWheelsTurningVehicle
{
	public String registrationNumber;    // Nr rejestracyjny samochodu
	public int frontWheelsTurnAngle;

	
	public void turn(int angle) {
            // Tutaj implementacja procesu zakręcania o określony kąt. Dla realizacji tego procesu
            // zostanie użyta w odpowiedni sposób metoda turnFrontWheels()
	}

	public void turnFrontWheels(int targetAngle) {
		// Tutaj implementacja procesu stopniowego skręcania przednich kół
	}

}