2013-08-22 3 views
12

Базовый класс:Наследование и объектов Создание

public class Inheritance { 
    int i; 
    Inheritance() { 
     System.out.println("I am in base class" + i); 
    } 
} 

производный класс:

public class TestInheritance extends Inheritance { 

    TestInheritance() { 
     System.out.println("I am in derived class"); 
    } 

    public static void main(String[] args) { 
     TestInheritance obj = new TestInheritance();   
    } 
} 

Это то, что я имею в виду относительно того, что происходит выше.

Когда я создаю объект производного класса по умолчанию, вызывается super() и вызывается конструктор базового класса и инициализирует переменную i.

Теперь, мой вопрос: имеет ли конструктор в этом случае только инициализацию переменной i и не создает конкретный объект класса?

Из того, что я прочитал до сих пор, существует только один объект, созданный из производного класса, в котором есть переменная i.

Но с момента вызова конструктора базового класса и момента времени, когда конструктор производного класса вызывается как/где i хранится в памяти?

И что будет в случае, если базовый класс является абстрактным.

Я был бы очень признателен, если бы знал, что происходит в памяти в разные моменты времени.

Если я сказал что-то, что является принципиально неправильным, пожалуйста, дайте мне знать. Я действительно хочу знать, как это работает.

+16

@Paniz Uh ... да, это так? – asteri

+1

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

+3

+1 - Хорошо структурированный вопрос - точный, задающий конкретные вопросы. –

ответ

4

Физически вы создали единый объект, но концептуально создали 2. Это как когда, скажем, родилась девочка: физически она только одна, но концептуально родилась новая женщина, а также новый человек родилось новое новообразованное существо, родился новый житель планеты Земля и т. д. Да, точно. Здесь тоже есть отношение наследования (subTyping), и я сделал это нарочно. Чтобы избежать путаницы, вероятно, лучше сказать, что существует только один объект с несколькими гранями; один объект, который является членом разных (супер-) классов одновременно.

Теперь, сказав достаточно о логической части, давайте рассмотрим физическую часть. Сингл (физический) объект создается со следующей структурой в памяти

+--------------------------+----------------------------+ 
|    B   |    C'   + 
+--------------------------+----------------------------+ 

Первая часть (В) содержит все поля, унаследованных от суперкласса B С (если таковая имеется). Вторая часть (C ', и я использую ' для «дополнения») содержит все поля, которые являются «проприетарными» для C (то есть не наследуются от B, а определяются самим C). Важно отметить, что созданный объект не запускается на C ', а на B. Это комбинация унаследованных полей с новыми полями, составляющими полный объект.

Теперь, если B имел свой собственный суперкласс А, структура была бы так:

+--------+-----------------+----------------------------+ 
| A |  B'   |    C'   + 
+--------+-----------------+----------------------------+ 

Что важно отметить, что B == A + B'. Другими словами, C не нужно знать о A. Все, что ему нужно, это его непосредственный суперкласс B, который скрывает его внутреннюю структуру.

Чтобы ответить на конкретные вопросы:

ли конструктор в этом случае только инициализировать переменную я и не создает конкретный объект класса?

Таким же образом, что A, B и C выше были структурно скованы цепью, они также прикованы к цепи при инициализации. Если бы это было не так, это было похоже на то, что девушка в моем оригинальном примере родилась без какой-либо другой вещи, которую мы знаю она также по определению. Это невозможно. Полное противоречие. Таким образом, выполняется процесс построения классов, который включает в себя: инициализация полей значением «нуля» (null для ссылок и false для boolean) и выполнение одного конструктора (который может вызывать другие конструкторы).

В данном конкретном случае, поле i инициализируется, Inheritance конструктор выполняется, «поля (если оно было), он будет инициализированы s, а затем TestInheritance» TestInheritance конструктор s был бы выполнен. Как мы можем точно сказать, какие конструкторы каждого класса? Относительно просто. Что инициировало все, это new TestInheritance(). Это, очевидно, указывает на то, что конструктор TestInheritance, который не имеет какого-либо параметра (который существует, в противном случае возникла ошибка компиляции). Однако этот конструктор явно не вызывает какой-либо конструктор суперкласса (через ключевое слово super(...)). Как мы видели выше, этого не может быть, и компилятор автоматически вставляет эквивалент super(), то есть вызов конструктора суперкласса без аргументов (Inheritance()). Опять же, этот конструктор существует, и все хорошо. Выход был бы:

I am in base class 0 
I am in derived class 

Конструкторов без параметров называется «по умолчанию конструкторов» для 3-х основных причин: - Они, как правило, очень просты, поскольку они не имеют параметров. - Они вызываются автоматически, когда конструктор подкласса явно не вызывает какой-либо конструктор суперкласса. - Они автоматически предоставляются для этих классов без какого-либо конструктора, написанного программистом. В этом случае конструктор ничего не делает, и происходит только инициализация.

Из того, что я прочитал до сих пор, создан только один объект - производного класса, который имеет переменную i.

Это не совсем правильно. Физически это правда, что был создан только один объект, но он соответствует классу, используемому с new (TestInheritance), который в этом случае не имеет полей, но это не имеет значения. Фактически, обе выходные линии печатаются. Концептуально ... мы уже это упомянули.

Но с момента вызова конструктора базового класса и момента времени, когда конструктор производного класса вызывается, как/где я сохранен в памяти?

Когда new TestInheritance() выполняются, то первое, что происходит перед конструкторами называется, даже до того, как выполняется инициализация, является то, что память выделяется для всего объекта. - Обычно эта память «грязная», поэтому ее нужно инициализировать. - Есть пространство для полей TestInheritance, полей суперкласса и т. Д. Даже положение каждого поля внутри объекта в памяти известно заранее.

Итак, еще до того, как вызывается конструктор базового класса, уже выделена память для i и любого другого поля, просто они «грязные» (не инициализированы).

И что будет в случае, если базовый класс является абстрактным.

Нет никакой разницы. Единственное, что вы сами не можете создавать объекты абстрактного класса. Вы создаете их как часть (конкретного) подкласса. Это похоже на то, что новый человек не может быть рожден сам. Это либо девочка, либо ребенок.

Я был бы очень признателен, если бы знал, что происходит в памяти в разные моменты времени.

Надеюсь, я сделал.

Если я сказал что-то, что является принципиально неправильным, пожалуйста, дайте мне знать. Я действительно хочу знать, как это работает.

Ничего "принципиально неправильного".

+0

Пара вопросов. Как супер() вызывает конструктор по умолчанию, что делает этот конструктор по умолчанию? И в вашем объяснении поля, которые исходят от супер класса B, кто их инициализирует, конструктор C или конструктор B? А также правильно ли утверждать, что объект B содержится внутри C '? – Prateek

+0

Хотелось бы, чтобы было больше способов выразить мою благодарность. Благодаря!!! – Prateek

2

Я думаю, что это общая область замешательства над наследованием. Вы, кажется, поняли, что создан только один объект, это правильно.

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

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

И одна терминологическая коррекция: в вашем коде переменная явно не «инициализирована» - я думаю, что вы хотите спросить о «распределении», т. Е. В какой точке переменная имеет свое пространство в памяти. «Инициализация» означает, что переменной присваивается значение, и хотя Java очень хорош в назначении значений по умолчанию для своих переменных, я думаю, что вы выделяете людей в этом случае.

+0

+1 хорошее объяснение! – alfasin

+0

Концептуально я полностью понял вашу мысль. Однако у меня есть вопрос. Что происходит, когда базовый класс является абстрактным? В этом случае то, что делает super() в производном классе. – Prateek

Смежные вопросы