Суперкласс obj = новый подкласс (); смысл и кастинг - PullRequest
0 голосов
/ 16 апреля 2020

Если у меня есть суперкласс (Животное) и подкласс (Кошка).

Что означает третий пункт? И когда нам нужно разыграть?

  1. Cat obj = new Cat(); означает создание объекта из класса Cat

  2. Animal obj = new Animal(); означает создание объекта из Animal класс

  3. Animal obj = new Cat();

Ответы [ 2 ]

1 голос
/ 16 апреля 2020

Сначала давайте разберемся с классом, ссылкой и объектом. Предположим, у нас есть класс с именем SomeClass

SomeClass ref = new SomeClass();

Выше у нас есть объект SomeClass, созданный в Heap, и ссылочная переменная ссылается на него. Мы назвали ссылочную переменную ref. Объект присутствует в куче, и мы можем просто получить к нему доступ, используя ссылку. Таким образом, Тип объекта относится к фактическому классу (к которому применено ключевое слово new). Тип ссылочной переменной может быть действительного класса или его родительского класса.

Теперь давайте посмотрим на связь наследования. Класс, унаследованный от другого класса, имеет общие отношения Child-Parent. Child наследует поведение своего Parent и может затем переопределить некоторые из поведения, а также может добавить некоторое дополнительное поведение. Следовательно, Object of Child может использоваться в любом месте, где ожидается родительский объект, так как Child имеет все поведение своего Parent, поэтому вызов любого поведения, присутствующего в Parent, будет обрабатываться Child.

Родительский класс не делает знать о дополнительном поведении своего дочернего класса (дочерний класс записывается позже). Следовательно, объект Parent не может быть использован в тех местах, где ожидается объект Child (если дополнительное поведение Child вызывается на объекте Parent, тогда он будет не будет чести).

Теперь давайте предположим, что у нас есть классы ParentClass и ChildClass, такие что ChildClass inherits ParentClass

ParentClass reference =  new ParentClass(); // Valid
ParentClass reference = new ChildClass(); //Valid
ChildClass reference = new ChildClass(); //Valid
ChildClass reference = new ParentClass();// Not Valid.

Обратите внимание, что ссылка на ParentClass = new ChildClass (); // Здесь Object имеет тип ChildClass, а Reference имеет тип ParentClass.

Теперь, когда разыграть. Любое место, ожидающее объект ParentClass, не нуждается в приведении, оба объекта (из ParentClass или ChildClass) в порядке. Любое место, ожидающее Объект типа ChildClass, но если у нас есть случай, подобный приведенному ниже, то приведение необходимо.

public void someMethod(ChildClass expected){
    //some implementation
}
ParentClass ref = new ChildClass();
someMethod(ref);//Invalid : Compilation Issue 
someMethod((ChildClass)ref);// Valid
ParentClass anotherRef = new ParentClass();
someMethod(anotherRef); // Invalid : Compilation Issue
someMethod((ChildClass)ref); //Invalid, compiles but Runtime it will fail. 

Правило большого пальца: Child - это Child, Child - родитель, Parent - родитель, Parent - не ребенок.

Еще один пример для понимания.

public abstract class List{
    public abstract void add(int element);
    public abstract void remove(int element);
   public int size();
}

public class Application{
    private  List listReference;
    public void setList(List ref){
         listReference = ref;
    }
}

//Now you may create sub classes as below 
public class ArrayList extends List{
     // all the abstract methods of List have been implemented 
}

public class LinkedList extends List{
    //all the abstract methods of List have been implemented
}

Теперь в методе main вы можете передать ArrayList или LinkedList или любую другую реализацию.

public class Init{
    public static void main(String[] args){
         Application app = new Application ();
         app.setList(new LinkedList());
         //or you can set it like this
         List listRef = bew ArrayList();
         app.setList(listRef);
         //or you can set it like this
         LinkedList linkedListRef = new LinkedLiet();
         app.setList(linkedListRef);
    }
}

Обратите внимание, что метод setList() принимает тип ссылки List, и мы можем предоставить любую реализацию абстракции List. Это приводит к гибкой конструкции. Занятия должны зависеть от абстракции. Программирование для интерфейса - это принцип разработки, который облегчает обслуживание кода приложения.

0 голосов
/ 16 апреля 2020

Причина, по которой это сбивает с толку, заключается в том, что это не то, что вы обычно делаете в реальном коде, за исключением случая с Фабрикой.

Как указывалось в комментарии Забузы, Вы можете сделать это, потому что Cat 'is-a' является видом Animal, и поэтому вы можете назначить объект типа Cat объекту типа Animal. Но вы, конечно, не можете выполнить задание иначе, потому что Animal - это не Cat.

Теперь есть некоторые скрытые проблемы, которые связаны с возможностью создания экземпляра супертипа, а также подтипа, что означает, что вы обычно не будете делать это в реальном коде, потому что это сильно усложняет. вещей в будущем. Скорее всего, вы бы сделали Animal интерфейсом и классом GenericAnimal, который его реализует, вместе с Cat реализующим его.

Скажем, у вас есть объект, представляющий зоопарк, и в большинстве зоопарков обычно есть коллекция животных. Наиболее очевидный способ представить это было бы так:

java.util.Collection<com.myproject.Animal> zooAnimals;

Итак, теперь представьте, что зоопарк строит новую среду обитания, и это для льва. Ради истории предположим, что у нас очень ленивая модель данных, и вместо того, чтобы иметь конкретный подтип c com.myproject.animals.cats.Lion, мы просто сказали: «львы - это кошки, достаточно близкие». Поэтому, чтобы обновить структуру данных, которая отслеживает всех животных, их имена, адреса, любимые продукты и все остальное, мы могли бы сделать это:

com.myproject.Animal newArrival = new com.myproject.animals.Cat("Larry the Lion", "Africa Exhibit", "Gazelles");
zooAnimals.add(newArrival);

Теперь представьте, что зоопарк продолжает расти и получает страуса. в среде обитания Африки. И та же самая ленивая модель данных применима, поэтому мы просто называем это Bird.

com.myproject.Animal newArrival = new com.myproject.animals.Bird("Oliver the Ostrich", "Africa Exhibit", "Whatever Ostriches Eat");
zooAnimals.add(newArrival);

Теперь на самом деле написание этого точного кода обычно происходит только в очень специфических c случаях внутри объекта фабрики или чего-то подобного, и реалистично подобранные иерархии типов имеют тенденцию вообще не очень хорошо работать, вопреки тому, что многие из нас узнали в классе объектно-ориентированного программирования, но ради вопроса, который является примером ситуации, когда вы могли бы сделать то, что Вы спрашиваете о.

Наконец, вы также спросили, когда вам нужно сыграть. Вы должны были бы сделать это, если бы у вас был код, который должен был знать о любых специальных методах или полях, которые есть у типов Cat или Bird, которых нет у Animal. Например, тип Cat может иметь свойство, называемое tailLength, потому что у кошек обычно есть хвосты, и по какой-то причине зоопарк любит отслеживать это. Точно так же тип Bird может иметь свойство, называемое wingSpan, потому что у птиц есть крылья, и мы хотим отслеживать, насколько они велики. Тип Animal не имеет ни одного из этих свойств, поэтому, если мы получим объект для льва или страуса из коллекции zooAnimals (и, возможно, мы посмотрели на имя или что-то еще, чтобы выяснить, что это был лев), нам бы пришлось приведите обратно к типу Cat, чтобы получить доступ к свойству tailLength. То же самое для страуса и его размах крыльев.

for( Animal theAnimal : zooAnimals ){
    if( theAnimal.getName().equals("Larry the Lion") ){
        Cat theCat = (Cat)theAnimal;
        System.out.println("Larry's tail is " + theCat.getTailLength() + " inches long";
    }
    else if( theAnimal.getName().equals("Oliver the Ostrich") ){
        Bird theBird = (Bird)theAnimal;
        System.out.println("Oliver's wingspan is " + theBird.getWingSpan() + " inches";
   }
}

Опять же, вы, вероятно, на самом деле не сделаете что-то подобное в реальном коде, но, возможно, это поможет проиллюстрировать пример.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...