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