здрасти Днес ще разгледаме по-подробно един принцип на обектно-ориентираното програмиране (ООП): Наследяване. Ще изучаваме и други видове връзки между класовете: композиция и агрегиране.
Тази тема няма да е трудна: вече сте се сблъсквали с наследяване и примери за наследяване много пъти в предишни уроци. Днес основното нещо ще бъде да затвърдите знанията си, да разгледате по-подробно механизма на наследяване и отново да преминете през някои примери. :) Е, давай!
Когато имаме няколко дузини класове автомобor, количеството дублиран code става наистина сериозно. Преместването на общи полета и методи (наричани още „състояния“ и „поведения“) към родителски клас ни позволява да спестим много време и място. Ако някой тип има уникални свойства or методи, които другите типове автомобor нямат, нищо страшно. Винаги можете да ги създадете в клас наследник, отделно от всички останали.
Същото важи и за полетата: ако дъщерен клас има уникални свойства, ние спокойно декларираме тези полета вътре в дъщерния клас и спираме да се тревожим. :) Възможността за повторно използване на code е основното предимство на наследяването. За програмистите е много важно да не пишат допълнителен code. Ще срещнете това многократно в работата си. Моля, запомнете нещо друго важно: Java няма множествено наследяване. Всеки клас наследява само един клас. Ще говорим повече за причините за това в следващите уроци. Засега просто го запомни. Между другото, това прави Java различна от някои други ООП езици. Например C++ поддържа множествено наследяване. Всичко е повече or по-малко ясно с наследството. Да продължим.

Наследяване в Java и неговите предимства
Както със сигурност си спомняте, наследяването е механизъм, който ви позволява да опишете нов клас въз основа на съществуващ клас (родителски клас). По този начин новият клас заема свойствата и функционалността на родителския клас. Нека си припомним пример за наследяване, даден в предишните уроци:
public class Car {
private String model;
private int maxSpeed;
private int yearOfManufacture;
public Car(String model, int maxSpeed, int yearOfManufacture) {
this.model = model;
this.maxSpeed = maxSpeed;
this.yearOfManufacture = yearOfManufacture;
}
public void gas() {
// Gas
}
public void brake() {
// Brake
}
}
public class Truck extends Car {
public Truck(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
public class Sedan extends Car {
public Sedan(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
Имаме определена програма, която включва работа с различни видове автомобor. Дори и да не сте автомобилен ентусиаст, вероятно знаете, че в света има много видове автомобor. :) Съответно ще разделим общите свойства на автомобorте в общ родителски клас, наречен Car
. И така, Howво е общото за всички автомобor, независимо от техния тип? Всяка кола има година на производство, име на модела и максимална скорост. Поставяме тези свойства в полетата model
, maxSpeed
и yearOfManufacture
. Що се отнася до поведението, всяка кола може да ускорява и забавя. :) Дефинираме това поведение в gas()
иbrake()
методи. Какви ползи ни носи това? На първо място, това намалява количеството code. Разбира се, можем и без родителския клас. Но тъй като всяка кола трябва да може да ускорява и забавя, ще трябва да създадем методи gas()
и brake()
в класовете Truck
, , и във всеки друг клас автомобor. Представете си колко допълнителен code ще трябва да напишем. И не забравяйте за полетата , , и : ако се отървем от родителския клас, ще трябва да ги създадем във всеки клас автомобor! Sedan
F1Car
SportsCar
model
maxSpeed
yearOfManufacture

public class F1Car extends Car {
public void pitStop() {
// Only race cars make pit stops
}
public static void main(String[] args) {
F1Car formula1Car = new F1Car();
formula1Car.gas();
formula1Car.pitStop();
formula1Car.brake();
}
}
Нека да разгледаме състезателните автомобor от Формула 1 като пример. За разлика от своите "роднини", те имат уникално поведение - спират от време на време. Това не ни притеснява. Вече описахме обичайното поведение в Car
родителския клас и специфичното поведение на наследствените класове може да бъде добавено към тези класове. 
Състав и агрегация
Класовете и обектите могат да бъдат свързани заедно. Наследяването описва връзка "е-е". Лъвът е животно. Такава връзка лесно се изразява с помощта на наследяване, къдетоAnimal
е родителският клас и Lion
е дъщерният. Не всички връзки обаче се описват по този начин. Например клавиатурата определено е свързана с компютър, но не е компютър . Ръцете по няHowъв начин са свързани с човек, но не са човек. В тези случаи имаме друг тип връзка: не „е-е“, а „има-а“. Ръката не е човек, но е част от човек. Клавиатурата не е компютър, но е част от компютър. Връзката има-а може да бъде описана в code с помощта на композиция и агрегиране. Разликата е в "строгостта" на връзката. Нека дадем прост пример: Имаме клас Car
. Всяка кола има двигател. Освен това всяка кола има пътници. Каква е основната разлика между полетата Engine engine
и Passenger[] passengers
? Фактът, че пътникът A
седи в колата, не означава, че пътниците B
и C
не са в колата. Една кола може да отговаря на няколко пътника. Нещо повече, ако всички пътници слязат от колата, тя ще продължи да работи гладко. Връзката между Car
класа и Passenger[] passengers
масива е по-малко строга. Нарича се агрегиране . Той предоставя друг добър пример за агрегиране. Да предположим, че имаме Student
клас и aStudentGroup
клас. Студент може да се присъедини към множество студентски организации: клуб по физика, фен клуб на Междузвездни войни и/or студентски комедиен клуб. Композицията е по-строг вид връзка. Когато използвате композиция, обектът е част от няHowъв обект и не може да принадлежи на друг обект от същия тип. Най-простият пример е автомобилен двигател. Двигателят е част от кола и не може да бъде част от друга кола. Както можете да видите, тяхната връзка е много по-строга от връзката между Car
и Passengers
. 
GO TO FULL VERSION