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

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

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

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

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

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

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

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

+183
источник поделиться
17 ответов

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

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

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

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

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

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

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

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

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

+190
источник

Да

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

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

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

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


Update:

Err, "Нет"

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

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

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

+62
источник

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


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

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

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

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


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

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

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

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

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

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

 

+16
источник

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

+9
источник

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

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

Например:

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

+8
источник

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

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

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

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

Родитель -

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 reallyHidden
            c1.reallyHidden;//Does not even compile

    }//main

}//Child
+8
источник

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

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

+4
источник

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

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

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

+3
источник

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

+3
источник

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

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

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

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

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

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

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

0
источник

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

0
источник

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

0
источник

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

0
источник

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

0
источник

Макет памяти в Java vis-a-vis inheritance

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

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

0
источник

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

-1
источник

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

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

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

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

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

-2
источник

Посмотрите другие вопросы по меткам или Задайте вопрос