Почему супер класс может быть инициализирован как дочерний класс в Java?

в двух словах, как и почему это возможно:

Object obj=new MyClass();

Object является суперклассом всех объектов, поэтому MyClass является дочерним классом объекта. В общем, на Java,Почему это можно использовать конструктор дочернего класса в родительском классе?


Я понимаю, как это может быть наоборот, так как у ребенка есть все переменные / методы родительского класса, поэтому при их инициализации вы просто инициализируете переменные, заданные в Родительском конструкторе, которые существуют по определению в дочернем. Проблема в том, что когда вы идете по другому пути, это не обязательно верно. ребенок может иметь переменные, которые родитель не, так как же можно использовать дочерний конструктор с родителем, когда родитель даже не имеет переменных в первую очередь?


что использует эта функция в разработке? Я думаю, что если вы хотите экземпляр из класса B вы объявите его как B thing=new B (), а не a thing=new B (). Вероятно, это говорит моя неопытность, поэтому я был бы признателен за разъяснение того, почему и как родительский класс может быть инициализирован как один из его детей.

8 ответов


почему можно использовать конструктор дочернего класса в родительский класс?

это неправильно. Когда вы делаете

Object obj = new MyClass();

Object obj; объявляет ссылку типа Object и new MyClass(); возвращает ссылку на созданный объект.

Итак, вы создаете экземпляр MyClass и присвоение ссылки на объект, созданный для ссылки типа Object, а это возможно, потому что MyClass - это Object.

как вы говорите,

у ребенка могут быть переменные, которые родитель не

это называется расширением родительской функциональности (наследование).

для вашего второго вопроса подумайте о классическом Animal пример: Предположим, вы создать Animal class и вы создаете метод makeSound() на нем.

теперь вы создаете два подкласса Animal, Dog и Cat, который переопределяет makeSound()метод Animal (a Dog лает и Cat мяукает).

представьте, что вы представляете комнату, полную Animals (Dogs и Cats) использование List, а вы хотите сделать все из них makeSound(). Ваш список будет объявлен как List<Animal> потому что вы не знаете вида Animals, которые вы будете хранить.

и затем вы повторяете List называть makeSound() для каждого Animal. Не имеет значения, если Animal это Dogили Cat, это будет звучать.

а потом представьте, что вы хотите добавить Birdдо List. Легко, не так ли?


вы думаете в терминах семантики C++, но это Java. В Java, все непримитивные переменные типа являются ссылками, а не экземпляры.

в C++, когда вы говорите

Object obj;

вы выделяете новый Object экземпляр в стеке или в статической памяти.

когда вы говорите

Object obj = new MyObject;

вы вызываете конструктор Object класса, который принимает MyObject указатель (или может быть что-то еще, что MyObject можно преобразовать к.)

В Java,

Object obj;

не создает никаких экземпляров Object. Он просто создает переменную, которая может иметь ссылку на Object экземпляр, но на данный момент не относится ни к одной. Он инициализируется в null.

Object obj = new MyObject();

выделяет экземпляр MyObject. Он не выделяет новый экземпляр Object. Он просто устанавливает переменную для ссылки на новый экземпляр. В терминах C++ это гораздо больше похоже на

Object *obj = new MyObject();

таким образом, мы не создаем Родительский экземпляр из дочернего экземпляра. Мы меняем значение переменной с null на новый дочерний экземпляр.


каждый класс в Java происходит от Object. Так что MyClass это Object по определению, но более специализированную версию. Подумайте об этом так: каждое живое существо-это Animal. А Cat это особый вид животного; определенный тип. С Cat это Animal, вы все еще можете просто назвать это Animal:

Animal a = new Cat();

но при этом, с a, вы не можете сделать ничего конкретного для Cat, как meow() или purr(), но вы можете вызвать методы, которые действительны для всех Animals, например breathe().

HTH


во-первых, вы должны получить четкое понимание вещей. Пример выражения: Object obj = new MyClass(); на самом деле соединение два элементарные операции.

первый из них создает экземпляр MyClass:new MyClass(). The new ключевое слово в основном является единственным способом получения экземпляра класса (позволяет игнорировать отражение среды выполнения, чтобы сохранить это простым), и вы буквально называете то, что хотите создать (MyClass) здесь своим конструктором. Нет возможности создайте что-нибудь, кроме того, что вы буквально назвали с новым ключевым словом. Результатом new является (неявно) экземпляр MyClass, но явный результат new X это ссылка типа X (ссылка, относящаяся к вновь созданному экземпляру).

теперь вторая операция присваивает ссылку на ваш (новый) MyObject другой ссылке типа Object. И это действительно, потому что MyObject is объект (из-за наследование.)

зачем вам это нужно?

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

примером реального мира будут графические пользовательские интерфейсы. Есть кнопки, списки, таблицы и панели в окне, которые являются элементами пользовательского интерфейса, но каждый из них делает разные вещи. Чтобы представить их аккуратно организованными в окне, эти элементы часто вложены в панели, более абстрактно сказано в тара. Теперь контейнеру все равно, какие элементы входят в него, пока они являются компонентами. Но правильно обращаться с ними контейнер тут нужна некоторая основная информация об этих компонентах, в основном, сколько места они занимают и как их рисовать. Таким образом, это моделируется как что-то вроде:

public abstract class Component {
    public int getWidth() { ... }

    public int getHeight() { ... }

    public void paint(Graphics g) { ... }
}

public class Container extends Component {
    public void add(Component child) { ... }

    public void paint(Graphics g) {
        for (Component child : children) {
            child.paint(g);
        }
    }
}

это почти прямо поднято из JDK, дело в том, что если вам нужно ссылаться на каждый компонент как на его конкретный тип, было бы непрактично создавать контейнер, ему нужен дополнительный код для каждого компонента, который вы решите сделать (например, будет addButton, addTable и так далее). Поэтому вместо этого контейнер просто работает со ссылкой на компонент. Независимо от того, какой компонент создается (например, кнопка, CheckBox, RadioButton etc.), так как контейнер просто полагается на них всем быть компонент, он может обрабатывать их.


class myMobile{
  public void call{
     System.out.println("Mobile");
      }
  }
    public class mainClass{
        public static void main(){
            Object o=new myMobile();
                //here we can call methods which are common to all 
                                     // objects not specific to 
                                                   // myMobile object
           }
  }

- за MyClass это Object. Обратите внимание, что java особенная, потому что Object является суперклассом любого другого типа класса (в C++нет эквивалента).

более интересным примером было бы, если бы у вас был класс или интерфейс и один или несколько подклассов. Это постоянно всплывает в Уде. Рассмотрим, например, java интерфейс API JDBC в: общий набор интерфейсов для подключения и запроса базы данных, которые могут быть реализованы различными конкретными классами. Вам нужно только закодировать API, а затем во время выполнения использовать реализацию для вашей БД по выбору.


enter image description here

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html

класса Object является корнем иерархии классов. Каждый класс имеет объект как суперкласс. Все объекты, включая массивы, реализуют методы этого класса.

то есть Java-класса-это Object. Вот почему.

http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

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


у вас есть две отдельные вещи здесь:

  • построение нового экземпляра
  • назначение этого экземпляра переменная

С вашего экземпляра MyClass тоже экземпляр Object, это хорошо работает.

рассмотрим следующую общую ситуацию:

class A extends B implements C,D {
}

в своем A это B и C и a D и Object, как только вы создали например, вы можете (прямо или косвенно) назначить его переменным всех этих типов:

A a = new A();
B b = a;
C c = a;
D d = a;
Object o = a;

код посмотреть на полях или методах ограничено типом переменной (i.E. в качестве переменной типа C вы видите только методы, объявленные C). Тем не менее, ваш экземпляр всегда типа вы instanciated С помощью конструктора, независимо от типа переменной.