Наследуют ли подclassы частные поля?

Это вопрос интервью.

Наследует ли подclassы частные поля?

Я ответил «Нет», потому что мы не можем получить к ним доступ, используя «обычный способ ООП». Но интервьюер считает, что они унаследованы, потому что мы можем косвенно коснуться таких полей или использовать reflection, и они все еще существуют в объекте.

После того, как я вернулся, я нашел следующую цитату в javadoc :

Частные члены в суперclassе

Подclass не наследует частных членов его родительского classа.

Знаете ли вы какие-либо аргументы для мнения интервьюера?

Большая часть путаницы в вопросе / ответах здесь охватывает определение Наследования.

Очевидно, что, поскольку @DigitalRoss объясняет, что OBJECT подclassа должен содержать частные поля суперclassа. По его словам, отсутствие доступа к частному члену не означает, что его нет.

Однако. Это отличается от понятия наследования для classа. Как и в мире Java, где есть вопрос о семантике, арбитр – это спецификация языка Java (в настоящее время 3-е издание).

Как указано в JLS ( https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2 ):

Члены classа, объявленные как private, не наследуются подclassами этого classа. Только члены classа, объявленные защищенными или общедоступными, наследуются подclassами, объявленными в пакете, отличном от того, в котором объявлен class.

Это касается точного вопроса, заданного интервьюером: «наследуют ли частные поля sub sub CLASSES ». (выделено мной мной)

Ответ: Нет. Они этого не делают. ОБЪЕКТЫ подclassов содержат частные поля их суперclassов. В самом подclassе нет NO NOTION частных полей своего суперclassа.

Это семантика педантичной природы? Да. Это вопрос полезного интервью? Возможно нет. Но JLS устанавливает определение для Java-мира и делает это (в данном случае) однозначно.

EDITED (удалена параллельная цитата из Bjarne Stroustrup, которая из-за различий между java и c ++, вероятно, только добавляет к путанице. Я позволю своему ответу отдохнуть на JLS 🙂

да

Важно понимать, что, хотя существуют два classа, существует только один объект.

Итак, да, конечно, он унаследовал частные поля. Они, по-видимому, необходимы для правильной функциональности объекта, и хотя объект родительского classа не является объектом производного classа, экземпляр производного classа в основном определенно является экземпляром родительского classа. Не может быть так, что без всех полей.

Нет, вы не можете напрямую обращаться к ним. Да, они унаследованы. Они должны быть.

Это хороший вопрос!


Обновить:

Err, “Нет”

Ну, я думаю, мы все чему-то научились. Поскольку JLS породила точную «ненасыщенную» формулировку, правильно ответить «нет» . Поскольку подclass не может получить доступ или изменить частные поля, то, другими словами, они не наследуются. Но на самом деле есть только один объект, он действительно содержит частные поля, поэтому, если кто-то неправильно формулирует JLS и учебник, будет довольно сложно понять ООП, объекты Java и то, что действительно происходит.

Обновление для обновления:

Противоречие здесь связано с фундаментальной двусмысленностью: что именно обсуждается? Объект? Или мы говорим в некотором смысле о самом classе? При описании classа в отличие от объекта допускается много широты. Таким образом, подclass не наследует частные поля, но объект, являющийся экземпляром подclassа, безусловно, содержит частные поля.

Нет. Частные поля не унаследованы … и поэтому Protected был изобретен. Это по дизайну. Думаю, это оправдывало существование защищенного модификатора.


Теперь перейдем к контекстам. Что вы подразумеваете под унаследованным – если оно есть в объекте, созданном из производного classа? да.

Если вы имеете в виду, это может быть полезно для производного classа. Ну нет.

Теперь, когда вы приходите к функциональному программированию, частное поле суперclassа не наследуется значимым образом для подclassа . Для подclassа частное поле суперclassа такое же, как частное поле любого другого classа.

Функционально это не унаследовано. Но в идеале это так.


Хорошо, просто посмотрел в учебник по Java, который они цитируют:

Частные члены в суперclassе

Подclass не наследует частных членов его родительского classа. Однако, если суперclass имеет общедоступные или защищенные методы для доступа к своим закрытым полям, они также могут использоваться подclassом.

обратитесь: http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html

Я согласен, что поле есть. Но подclass не получает никаких привилегий в этом частном поле. В подclass частное поле такое же, как любое частное поле любого другого classа.

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

Это зависит от вашего определения «наследовать». Есть ли в подclassе все поля в памяти? Определенно. Может ли он получить к ним доступ напрямую? Нет. Это просто тонкости определения; дело в том, чтобы понять, что на самом деле происходит.

Я продемонстрирую концепцию с кодом. Подclassы ACTUALLY наследуют частные переменные суперclassа. Единственная проблема заключается в том, что они недоступны для дочерних объектов, если вы не предоставляете публичные геттеры и сеттеры для частных переменных в суперclassе.

Рассмотрим два classа в пакете Dump. Ребенок распространяется на родителя.

Если я правильно помню, дочерний объект в памяти состоит из двух регионов. Одна из них – только родительская часть, а другая – только дочерняя. Ребенок может получить доступ к частному разделу в коде своего родителя только через открытый метод в родительском.

Подумайте об этом так. Отец Бората Болток имеет сейф, содержащий 100 000 долларов. Он не хочет делиться своей «частной» переменной безопасностью. Таким образом, он не предоставляет ключ для сейфа. Борат наследует сейф. Но, что хорошего, если он не может даже открыть его? Если бы только его отец предоставил ключ.

Родитель –

 package Dump; public class Parent { private String reallyHidden; private String notReallyHidden; public String getNotReallyHidden() { return notReallyHidden; } public void setNotReallyHidden(String notReallyHidden) { this.notReallyHidden = notReallyHidden; } }//Parent 

Ребенок –

 package Dump; public class Child extends Parent { private String childOnly; public String getChildOnly() { return childOnly; } public void setChildOnly(String childOnly) { this.childOnly = childOnly; } public static void main(String [] args){ System.out.println("Testing..."); Child c1 = new Child(); c1.setChildOnly("childOnly"); c1.setNotReallyHidden("notReallyHidden"); //Attempting to access parent's reallyHidden c1.reallyHidden;//Does not even compile }//main }//Child 

Нет. Они не наследуют его.

Тот факт, что какой-то другой class может использовать его, косвенно ничего не говорит о наследовании, а об инкапсуляции.

Например:

 class Some { private int count; public void increment() { count++; } public String toString() { return Integer.toString( count ); } } class UseIt { void useIt() { Some s = new Some(); s.increment(); s.increment(); s.increment(); int v = Integer.parseInt( s.toString() ); // hey, can you say you inherit it? } } 

Вы также можете получить значение count внутри UseIt через reflection. Это не значит, что вы наследуете его.

ОБНОВИТЬ

Несмотря на то, что значение есть, он не наследуется подclassом.

Например, подclass определяется как:

 class SomeOther extends Some { private int count = 1000; @Override public void increment() { super.increment(); count *= 10000; } } class UseIt { public static void main( String ... args ) { s = new SomeOther(); s.increment(); s.increment(); s.increment(); v = Integer.parseInt( s.toString() ); // what is the value of v? } } 

Это точно такая же ситуация, как и в первом примере. count атрибутов скрыт и не наследуется подclassом вообще. Тем не менее, как отмечает DigitalRoss, значение есть, но не средством наследования.

Положите это так. Если ваш отец богат и дает вам кредитную карту, вы все равно можете покупать вещи своими деньгами, но это не значит, что вы унаследовали все эти деньги, не так ли?

Другое обновление

Интересно, однако, знать, почему атрибут есть.

У меня, честно говоря, нет точного термина, чтобы описать его, но это JVM и способ его работы, который также загружает «не унаследованное» родительское определение.

Мы могли бы изменить родителя, и подclass все равно будет работать.

Например :

 //A.java class A { private int i; public String toString() { return ""+ i; } } // B.java class B extends A {} // Main.java class Main { public static void main( String [] args ) { System.out.println( new B().toString() ); } } // Compile all the files javac A.java B.java Main.java // Run Main java Main // Outout is 0 as expected as B is using the A 'toString' definition 0 // Change A.java class A { public String toString() { return "Nothing here"; } } // Recompile ONLY A.java javac A.java java Main // B wasn't modified and yet it shows a different behaviour, this is not due to // inheritance but the way Java loads the class Output: Nothing here 

Я думаю, что точный термин можно найти здесь: Спецификация виртуальной машины JavaTM

Хорошо, это очень интересная проблема, которую я много исследовал, и пришел к выводу, что частные члены суперclassа действительно доступны (но недоступны) в объектах подclassа. Чтобы доказать это, вот пример кода с родительским classом и дочерним classом, и я пишу объект classа child в txt-файл и читаю закрытый файл с именем «bhavesh» в файле, следовательно, он действительно доступен в дочернем class, но недоступен из-за модификатора доступа.

 import java.io.Serializable; public class ParentClass implements Serializable { public ParentClass() { } public int a=32131,b,c; private int bhavesh=5555,rr,weq,refw; } 

 import java.io.*; import java.io.Serializable; public class ChildClass extends ParentClass{ public ChildClass() { super(); } public static void main(String[] args) { ChildClass childObj = new ChildClass(); ObjectOutputStream oos; try { oos = new ObjectOutputStream(new FileOutputStream("C:\\MyData1.txt")); oos.writeObject(childObj); //Writing child class object and not parent class object System.out.println("Writing complete !"); } catch (IOException e) { } } } 

Откройте MyData1.txt и найдите частного участника с именем «bhavesh». Пожалуйста, дайте мне знать, что вы, ребята, думаете.

Ну, мой ответ на вопрос интервьюера – Частные члены не наследуются в подclassах, но они доступны для объекта подclassа или подclassа только через общедоступные методы getter или setter или любые такие подходящие методы исходного classа. Обычная практика заключается в том, чтобы держать членов закрытыми и обращаться к ним с использованием методов getter и setter, которые являются общедоступными. Итак, что означает только наследование методов getter и setter, когда частный член, с которым они имеют дело, недоступен для объекта? Здесь «унаследованный» просто означает, что он доступен непосредственно в подclassе, чтобы воспроизводить новые методы в подclassе.

Сохраните указанный ниже файл как ParentClass.java и попробуйте сами ->

 public class ParentClass { private int x; public int getX() { return x; } public void setX(int x) { this.x = x; } } class SubClass extends ParentClass { private int y; public int getY() { return y; } public void setY(int y) { this.y = y; } public void setXofParent(int x) { setX(x); } } class Main { public static void main(String[] args) { SubClass s = new SubClass(); s.setX(10); s.setY(12); System.out.println("X is :"+s.getX()); System.out.println("Y is :"+s.getY()); s.setXofParent(13); System.out.println("Now X is :"+s.getX()); } } Output: X is :10 Y is :12 Now X is :13 

Если мы попытаемся использовать приватную переменную x из ParentClass в методе SubClass, тогда она не будет доступна для любых изменений (значит, не унаследована). Но x может быть изменен в SubClass с помощью метода setX () исходного classа, как это сделано в методе setXofParent (), или его можно модифицировать с использованием объекта ChildClass с помощью метода setX () или метода setXofParent (), который в конечном итоге вызывает setX (). Таким образом, здесь setX () и getX () являются своеобразными воротами частного члена x ParentClass.

Еще один простой пример: Clock supercllass имеет часы и минуты как частные члены, а соответствующие методы getter и setter – публичные. Затем приходит DigitalClock в качестве подclassа Clock. Здесь, если объект DigitalClock не содержит часов и минут, тогда все прикручивается.

Казалось бы, подclass действительно наследует частные поля тем, что эти поля используются во внутренних работах подclassа (философски говоря). Подclass в своем конструкторе вызывает конструктор суперclassа. Закрытые поля суперclassа, очевидно, унаследованы подclassом, вызывающим конструктор суперclassа, если конструктор суперclassа инициализировал эти поля в его конструкторе. Это всего лишь пример. Но, конечно же, без методов доступа, подclass не может получить доступ к закрытым полям суперclassа (это похоже на то, что он не может вскрыть заднюю панель iPhone, чтобы вытащить батарею, чтобы перезагрузить телефон … но батарея все еще там).

PS Одно из многих определений наследования, которое я встретил: «Наследование – метод программирования, который позволяет производному classу расширять функциональность базового classа, наследуя все его СОСТОЯНИЕ (акцент мой) и поведение».

Частные поля, даже если они недоступны подclassом, являются унаследованным состоянием суперclassа.

Макет памяти в Java vis-a-vis наследования

введите описание изображения здесь

Биты заполнения / выравнивание и включение classа объектов в VTABLE не рассматриваются. Таким образом, объект подclassа имеет место для частных членов classа Super. Однако доступ к объектам подclassа невозможен.

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

Можем ли мы напрямую получить доступ к закрытому полю суперclassа из своего подclassа?

Затем ответьте « Нет» , если мы рассмотрим детали спецификатора доступа , упоминается, что частные члены доступны только внутри самого classа.

Но если вопрос

Можем ли мы получить доступ к закрытому полю суперclassа из своего подclassа?

Это означает, что не имеет значения, что вы сделаете для доступа к частному участнику. В этом случае мы можем сделать открытый метод в суперclassе, и вы можете получить доступ к частному члену. Итак, в этом случае вы создаете один интерфейс / мост для доступа к частному члену.

Другие языки ООП, такие как C ++, имеют концепцию friend function , благодаря которой мы можем получить доступ к частному члену другого classа.

Я думаю, что частное поле не наследуется, потому что подclass не может получить к нему доступ напрямую. или по-другому, я думаю, что только метод (включая доступ к частному полю) унаследовал, но не поле.

Мы можем просто заявить, что когда суперclass наследуется, частные члены суперclassа фактически становятся частными членами подclassа и не могут быть дополнительно унаследованы или недоступны для объектов подclassа.

Я должен был бы ответить, что частные поля в Java наследуются. Позвольте мне продемонстрировать:

 public class Foo { private int x; // This is the private field. public Foo() { x = 0; // Sets int x to 0. } //The following methods are declared "final" so that they can't be overridden. public final void update() { x++; } // Increments x by 1. public final int getX() { return x; } // Returns the x value. } public class Bar extends Foo { public Bar() { super(); // Because this extends a class with a constructor, it is required to run before anything else. update(); //Runs the inherited update() method twice update(); System.out.println(getX()); // Prints the inherited "x" int. } } 

Если вы запустите в программе Bar bar = new Bar(); , тогда вы всегда увидите номер «2» в окне вывода. Поскольку целое число «x» инкапсулируется методами update() и getX() , тогда можно доказать, что целое наследуется.

Путаница в том, что, поскольку вы не можете напрямую обращаться к целому «x», то люди утверждают, что он не унаследован. Однако каждая нестатическая вещь в classе, будь то поле или метод, наследуется.

Частный член classа или конструктор доступен только внутри тела classа верхнего уровня ( §7.6 ), который включает объявление члена или конструктора. Он не наследуется подclassами. https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6

Подclass не наследует частных членов его родительского classа. Однако, если суперclass имеет общедоступные или защищенные методы для доступа к своим закрытым полям, они также могут использоваться подclassом.

Частные члены (состояние и поведение) наследуются. Они (могут) влияют на поведение и размер объекта, который создается экземпляром classа. Не говоря уже о том, что они очень хорошо видны подclassам через все доступные механизмы захвата, или могут быть приняты их разработчиками.

Хотя наследование имеет определение «defacto», оно определенно не имеет никакого отношения к аспектам «видимости», которые воспринимаются «нет» ответами.

Поэтому нет необходимости быть дипломатическим. На данный момент JLS просто ошибается.

Любое предположение о том, что они не «унаследованы», небезопасно и опасно.

Таким образом, среди двух дефакто (частично) противоречивых определений (которые я не буду повторять), единственное, что следует соблюдать, – это безопасное (или безопасное).

Interesting Posts

SFINAE работает в обратном типе, но не как параметр шаблона

Создание отдельного списка настраиваемого типа в C #

Как я могу управлять тем, как Emacs создает файлы резервных копий?

Удаленный рабочий стол: запрос перед выходом из системы

Избегайте ввода пароля для ключей и подсказок для информации о DN

Кнопка обновления – Обновление сетки данных после вставки, удаления, обновления

SSE целочисленное деление?

Изменение формата даты в R

Вставка сертификата (с закрытым ключом) в корне, хранилище сертификатов LocalMachine не выполняется в .NET 4

Множественное перечисление значений в Obj-C

Найти прикрепленные / связанные события элемента с помощью инструментов разработки Chrome / Firebug / IE

Освобождение временных COM-объектов

Как правильно получить доступ к Google через IPV6?

Какие операции в Java считаются атомными?

Каков наиболее эффективный способ конкатенации N массивов?

Давайте будем гением компьютера.