子类是否继承私有字段?

Sta*_*lin 233 java oop inheritance private

这是一个面试问题.

子类是否继承私有字段?

我回答"否",因为我们无法使用"正常的OOP方式"访问它们.但是访谈者认为它们是继承的,因为我们可以间接访问这些字段或使用反射,它们仍然存在于对象中.

我回来后,在javadoc中找到以下引用:

超级私人会员

子类不继承其父类的私有成员.

你知道面试官的意见吗?

rob*_*x44 226

问题/答案中的大部分混淆都围绕着继承的定义.

显然,正如@DigitalRoss所解释的那样,子类的OBJECT必须包含其超类的私有字段.正如他所说,无法访问私人会员并不意味着它不存在.

然而.这与类的继承概念不同.正如java世界中存在语义问题的情况一样,仲裁器是Java语言规范(目前是第3版).

正如JLS所述(https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2):

声明为private的类的成员不会被该类的子类继承.只有声明为protected或public的类的成员才会被声明在声明类之外的包中声明的子类继承.

这解决了采访者提出的确切问题:"做子CLASSES继承私有领域".(我强调的是)

答案是否定的.他们没有.子类的OBJECTS包含其超类的私有字段.子类本身没有超类私有字段的NO OFTION.

这是一种迂腐的语义吗?是.这是一个有用的面试问题吗?可能不是.但是JLS建立了Java世界的定义,并且它(在这种情况下)明确地这样做了.

EDITED(删除了Bjarne Stroustrup的并行引用,因为java和c ++之间的差异可能只会增加混乱.我会让我的答案依赖于JLS :)

  • 调和所有这一切的一种方法是简单地认识到单词*"inherit"*以两种截然不同的方式用于描述派生类和父类的关系,至少在Java世界中是这样.是的,JSL是权威的.是的,这意味着您可以以不幸的方式使用"继承".但是,子类froggle(因为现在我们没有一个单词)的父类的私有字段仍然显而易见. (4认同)
  • @digital为什么感叹.我知道你相信你是对的.我并不反对你,对象继承是大多数程序员所教授/思考的.但JLS定义直接适用于原始问题.这是语义,但JLS决定了定义,而不是你或我. (2认同)
  • 任何人都有来自Java/Oracle的引用,因为"子类的对象包含其超类的私有字段"?我同意这一点,但找不到任何官方文件说. (2认同)

Dig*_*oss 73

认识到,虽然有很重要两个班,只有一个对象.

所以,是的,当然它继承了私有领域.它们可能是正确的对象功能必不可少的,虽然父类的对象不是派生类的对象,但派生类的实例绝对是父类的实例.如果没有所有的领域,那就不可能.

不,你不能直接访问它们.是的,他们是继承的.他们必须是.

这是一个很好的问题!


更新:

呃,"不"

好吧,我想我们都学到了一些东西.由于JLS起源于确切的"未继承"措辞,因此回答"否"是正确的.由于子类无法访问或修改私有字段,因此,换句话说,它们不会被继承.但是,真的只是一个对象,它真的确实包含了私人领域,因此,如果有人花JLS和教程措辞错误的方式,这将是相当困难的理解面向对象,Java对象,什么是真正发生.

更新更新:

这里的争议涉及一个基本的模糊性:究竟在讨论什么?对象? 或者我们在某种意义上谈论班级本身? 在描述类而不是对象时允许大量的纬度.因此子类不继承私有字段,但作为子类实例的对象肯定包含私有字段.

  • -1,Java语言规范清楚地说明它们不是继承的.不,如果没有,但没有.他们根本就没有.在Java的上下文中,任何其他继承定义都是错误的. (4认同)
  • @ Ma99uS.当然,它们可以重复使用.这就是整个继承点.如果没有它们,派生类型将不会也不会是父类型的实例.OOP将毫无意义.多态类型*将停止工作*.了解只有一个对象并且您是父类型的实例对于理解OOP至关重要.你必须完成这个问题才能理解它. (2认同)
  • 不确定父亲的例子是非常好的,因为在父类仍然存在的情况下可以继承字段并且还具有该字段.如果继承以这种方式运作,我可以在他活着的时候继承我父亲的钱,他也能保住同样的钱.我的孩子们每个人都有他的钱和我的钱. (2认同)
  • @Peter Lawrey没有争论或任何事情,但这就是我的想法.父母有一辆"汽车",他把它放在一个"私人"储物柜里,孩子不是钥匙.你确实继承了"汽车",但它对你没用.所以,实际上,你并没有从继承中受益. (2认同)
  • 我同意你的观点,只需确认一下:超类的私有方法也包含在子类的对象中,对吗? (2认同)

Nis*_*ant 20

不.私人领域不是继承的......这就是为什么发明了Protected的原因.这是设计的.我想这证明了保护修饰语的存在.


现在来到这里.你继承的意思是什么 - 如果在派生类创建的对象中存在?是的.

如果你的意思是它对派生类有用.好吧,不.

现在,当你进入函数式编程时,超类的私有字段不会以有意义的方式为子类继承.对于子类,超类的私有字段与任何其他类的私有字段相同.

从功能上讲,它不是遗传的.但理想情况是,它是.


好的,只是看看他们引用的Java教程:

超级私人会员

子类不继承其父类的私有成员.但是,如果超类具有访问其私有字段的公共或受保护方法,则子类也可以使用这些方法.

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

我同意,那个领域就在那里.但是,子类在该私有字段上没有任何特权.对于子类,私有字段与任何其他类的任何私有字段相同.

我认为这纯粹是观点问题.你可以在任何一方塑造争论.这两种方式都更合理.

 

  • 这是不正确的.您无法访问它们,这是正确的.但正如我所解释的那样,他们*必须继承. (2认同)

Meh*_*dad 12

这取决于你对"继承"的定义.子类是否仍有内存中的字段?当然.可以直接访问它们吗?不,这只是定义的微妙之处; 关键是要了解真正发生的事情.


Osc*_*Ryz 10

不,他们没有继承它.

其他一些类可能间接使用它的事实没有提到继承,而是关于封装.

例如:

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?
     }
}
Run Code Online (Sandbox Code Playgroud)

您还可以通过反射获取count内部的值UseIt.这并不意味着,你继承了它.

UPDATE

即使值存在,它也不会被子类继承.

例如,子类定义为:

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?           
     }
}
Run Code Online (Sandbox Code Playgroud)

这与第一个示例完全相同.该属性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
Run Code Online (Sandbox Code Playgroud)

我想这里可以找到确切的术语: JavaTM虚拟机规范

  • 它们“必须”被继承,多态类型才具有任何意义。看我的解释。确实,你无法摆弄它们,但它们就在那里。他们“必须”是。 (2认同)

Bor*_*yev 10

我将用代码演示这个概念.子类ACTUALLY 继承超类的私有变量.唯一的问题是除非您为超类中的私有变量提供公共getter和setter,否则它们不能被子对象访问.

考虑Dump包中的两个类.孩子延伸父母.

如果我没记错的话,内存中的子对象由两个区域组成.一个是父部分,另一个是子部分.子级只能通过父级中的公共方法访问其父级代码中的私有区域.

这样想吧.波拉特的父亲博尔托克有一个10万美元的保险箱.他不想分享他的"私人"变量安全.所以,他没有为保险箱提供钥匙.波拉特继承了保险箱.但是,如果他甚至不能打开它会有什么好处呢?如果只有他的父亲提供了钥匙.

家长 -

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
Run Code Online (Sandbox Code Playgroud)

孩子 -

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
Run Code Online (Sandbox Code Playgroud)


dga*_*002 6

我对面试官问题的回答是:私有成员不是在子类中继承的,但只能通过公共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
Run Code Online (Sandbox Code Playgroud)

如果我们尝试在SubClass的方法中使用ParentClass的私有变量x,那么它不能直接访问任何修改(意味着不继承).但是可以通过setXofParent()方法中的原始类的setX()方法在SubClass中修改x,或者可以使用setX()方法或最终调用setX()的setXofParent()方法使用ChildClass对象修改x.所以这里setX()和getX()是ParentClass的私有成员x的一种门.

另一个简单的例子是Clock超类将小时和分钟作为私有成员,并将适当的getter和setter方法作为public.然后DigitalClock作为Clock的子类.如果DigitalClock的对象不包含小时和分钟成员,那么事情就搞砸了.

  • 根据Oracle doc - 子类不继承其父类的私有成员.但是,如果超类具有访问其私有字段的公共或受保护方法,则子类也可以使用这些方法. (2认同)

Bha*_*wal 5

好吧,这是一个非常有趣的问题,我研究了很多并得出结论:超类的私有成员确实在子类的对象中可用(但不可访问)。为了证明这一点,这里是一个包含父类和子类的示例代码,我将子类对象写入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;
}
Run Code Online (Sandbox Code Playgroud)
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) {
    }


}
}
Run Code Online (Sandbox Code Playgroud)

打开 MyData1.txt 并搜索名为“bhavesh”的私有成员。请告诉我你们的想法。