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


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

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

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

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

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

A подкласс не наследует private члены родительского класса.

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

17 211

17 ответов:

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

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

да

важно понимать, что пока есть are два класса, есть только один объект.

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

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

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


обновление:

Err, "Нет"

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

нет. Частные поля не наследуются... и вот почему защищенный придумали. Это сделано специально. Я думаю, это оправдывает существование защищенного модификатора.


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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

родитель -

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

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

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

ок, это очень интересная проблема, которую я исследовал много и пришел к выводу, что частные члены суперкласса станут доступны (но не работает) в объекты подкласса. Чтобы доказать это, вот пример кода с родительским классом и дочерним классом, и я пишу объект дочернего класса в txt-файл и читаю частный член с именем "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 и поиск частного члена по имени "Бхавеш". Пожалуйста, дайте мне знать, что вы думаете.

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

частные поля, даже если подкласс недоступен, это наследуемое состояние суперкласса.

Memory Layout in Java vis-a-vis inheritance

enter image description here

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

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

у нас можете напрямую доступ к закрытому полю супер-класс их суб-класс ?

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

но, если вопрос это

можем ли мы получить доступ к закрытому полю суперкласса из их суб-класс ?

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

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

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

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

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", то люди утверждают, что это не так унаследованный. Однако каждая нестатическая вещь в классе, будь то поле или метод, наследуется.

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

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

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

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

хотя наследование имеет определение "defacto", оно определенно не имеет связи с аспектами "видимости", которые предполагаются "нет" ответы.

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

любое предположение, что они не "наследуются", небезопасно и опасно.

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