1. Преобразуване на типове
Променливите, които съхраняват референтни типове (класове), също могат да бъдат конвертирани в различни типове. Но това работи само в йерархия от един тип. Нека да разгледаме един прост пример. Да предположим, че имаме следната йерархия на класовете, в която класовете по-долу наследяват класовете по-горе.
Преобразуването на типове на референтни типове, Howто и на примитивни, също се категоризира като разширяване и стесняване.
Виждаме, че класът Cat наследява класа Pet, а класът Pet на свой ред наследява класа Animal.
Ако напишем code по този начин:
Animal kitten = new Cat();
Това е преобразуване на разширяващ се тип . Нарича се още имплицитно предаване. Разширихме препратката към котката , така че вече се отнася до обект Cat . С подобно преобразуване на типове няма да можем да използваме препратката към котето за извикване на методи, които присъстват в класа Cat , но липсват в класа Animal .
Стесняващо преобразуване (or изрично предаване) се случва в обратната посока:
Cat cat = (Cat) kitten;
Ние изрично посочихме, че искаме да прехвърлим препратката, съхранена в променливата kitten (чийто тип е Animal ) към типа Cat .
2. Проверка на типа на обект
Но тук трябва да сте много внимателни. Ако направите това:
Animal beast = new Cat();
Wolf grayWolf = (Wolf) beast;
Компилаторът ще позволи този code, но ще има грешка, когато програмата се изпълнява! JVM ще хвърли изключение:
Exception in thread "main" java.lang.ClassCastException: Cat cannot be cast to a Wolf
Препратките към обект Cat могат да се съхраняват само в променливи, чийто тип е предшественик на класа Cat: Pet, Animal or Object.
Защо така?
Съответният момент тук е, че препратката към обект се използва за препратка към методите и променливите на този обект . И няма да има проблеми, ако използваме променлива Animal, за да съхраним препратка към обект Cat: типът Cat винаги има променливи и методи от типа Animal — той ги е наследил!
Но ако JVM ни позволи да съхраним препратка към обект Cat в променлива Wolf, тогава може да имаме ситуация, в която може да се опитаме да използваме променливата grayWolf , за да извикаме метод, който не съществува в обекта Cat, съхранен в тази променлива . Ето защо тази подредба не е разрешена.
Java има специален instanceof
оператор, който ви позволява да проверите дали даден обект е от определен тип и следователно може да бъде съхранен в променлива от определен тип. Изглежда доста просто:
variable instanceof Type
Пример:
Animal beast = new Cat();
if (beast instanceof Wolf)
{
Wolf grayWolf = (Wolf) beast;
}
Този code няма да причини грешки — дори по време на изпълнение.
Ето още няколко примера, които илюстрират ситуацията:
Разширено преобразуване на типове | Описание |
---|---|
|
Това е класическо разширяващо преобразуване — не се изисква оператор за преобразуване на тип. Сега само методите, дефинирани в На |
Преобразуване на стесняващ тип | |
|
Класическо стесняващо преобразуване: Трябва да добавите проверка на типа и оператор за предаване. Променливата Cow cow съхранява препратка към Whale обект. Проверяваме дали това е така и след това извършваме (стесняващо) преобразуване на типа. Или Howто още се нарича:
тип отливка
.
|
|
Можете да стесните референтен тип, без да проверявате типа на обекта. Ако cow променливата се отнася до обект, който не е Whale , тогава InvalidClassCastException ще бъде генериран. |
3. Извикване на оригиналния метод: super
ключовата дума
Когато заместваме метода на родителския клас, понякога instead of да го заменим с наш собствен, искаме само леко да го допълним.
Би било страхотно, ако можем да използваме метода на родителския клас в нашия метод и след това да изпълним част от нашия собствен code. Или може би първо да изпълним нашия собствен code и след това да извикаме метода на родителския клас.
И Java ни позволява точно това. За да извикате метод на родителския клас, направете следното:
super.method(arguments);
Примери:
class PeaceTime
{
public double getPi()
{
return 3.14;
}
}
class WarTime extends PeaceTime
{
public double getPi()
{
return super.getPi()*2; // 3.14*2
}
}
Във военно време стойността на Pi
може да бъде по-голяма от 6! Разбира се, ние се шегуваме, но този пример показва How всичко това може да работи.
Ето още няколко примера, за да изясним малко нещата:
Код | Описание |
---|---|
|
Cow и Whale класове |
|
Изходът на екрана ще бъде:
|
Това са трудни неща. Честно казано, това е едно от най-трудните неща в OOP . Въпреки това трябва да го знаете и разбирате.
GO TO FULL VERSION