Подклассы наследуют частные поля? - PullRequest
227 голосов
/ 17 января 2011

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

Наследуют ли подклассы приватные поля?

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

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

Закрытые члены в суперклассе

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

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

Ответы [ 17 ]

224 голосов
/ 17 января 2011

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

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

Тем не менее. Это отличается от понятия наследования для класса. Как и в случае с Java, где существует вопрос семантики, арбитром является Спецификация языка Java (в настоящее время третье издание).

Как говорится в JLS (https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2):

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

Это отвечает на точный вопрос, заданный интервьюером: «делай суб КЛАССЫ наследуй частные поля». (выделено мной)

Ответ - нет. Нет. ОБЪЕКТЫ подклассов содержат частные поля своих суперклассов. У самого подкласса нет НИКАКОГО ПОНИМАНИЯ частных полей своего суперкласса.

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

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

72 голосов
/ 17 января 2011

Да

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

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

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

Хороший вопрос!


Обновление:

Ошибка "Нет"

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

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

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

18 голосов
/ 17 января 2011

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


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

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

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

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


ОК, только что посмотрел учебник по Java, они цитируют это:

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

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

см .: http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html

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

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

11 голосов
/ 17 января 2011

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

10 голосов
/ 12 мая 2014

Я продемонстрирую концепцию с кодом. Подклассы АКТУАЛЬНО наследуют приватные переменные суперкласса. Единственная проблема заключается в том, что они не доступны для дочерние объекты, если вы не предоставляете общедоступные методы получения и установки для частных переменных в супер классе.

Рассмотрим два класса в пакете 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
9 голосов
/ 17 января 2011

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

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

Например:

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 с помощью отражения.Это не значит, что ты наследуешь это.

ОБНОВЛЕНИЕ

Даже если значение присутствует, оно не наследуется подклассом.

Например, подкласс, определенный как:

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 скрыт и не вообще унаследован подклассом.Тем не менее, как указывает DigitalRoss, значение есть, но не посредством наследования.

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

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

Тем не менее, очень интересно узнать, почему атрибут существует.

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

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

Например, :

//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

6 голосов
/ 04 сентября 2013

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

Сохраните приведенный ниже файл как 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 () исходного класса, как это делается в методе setXofParent () ИЛИ его можно изменить с помощью объекта ChildClass с помощью метода setX () или метода setXofParent (), который в конечном итоге вызывает setX ().Таким образом, здесь setX () и getX () являются своего рода воротами к приватному члену x ParentClass.

Другой простой пример - суперкласс Clock имеет часы и минуты как частные члены и соответствующие методы getter и setter как public.Затем идет DigitalClock как подкласс часов.Здесь, если объект DigitalClock не содержит часов и минут, тогда все испорчено.

4 голосов
/ 31 мая 2012

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

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». Пожалуйста, дайте мне знать, что вы, ребята, думаете.

3 голосов
/ 04 февраля 2012

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

PS Одно из многих определений наследования, с которыми я сталкивался: «Наследование - метод программирования, который позволяет производному классу расширять функциональные возможности базового класса, наследуя все его состояние STATE (выделено мое) иповедение. "

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

1 голос
/ 08 января 2013

Нет , частные поля не наследуются. Единственная причина в том, что подкласс не может получить к ним доступ напрямую .

...