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 :)
Dig*_*oss 73
认识到,虽然有很重要的两个班,只有一个对象.
所以,是的,当然它继承了私有领域.它们可能是正确的对象功能必不可少的,虽然父类的对象不是派生类的对象,但派生类的实例绝对是父类的实例.如果没有所有的领域,那就不可能.
不,你不能直接访问它们.是的,他们是继承的.他们必须是.
这是一个很好的问题!
更新:
好吧,我想我们都学到了一些东西.由于JLS起源于确切的"未继承"措辞,因此回答"否"是正确的.由于子类无法访问或修改私有字段,因此,换句话说,它们不会被继承.但是,真的是只是一个对象,它真的确实包含了私人领域,因此,如果有人花JLS和教程措辞错误的方式,这将是相当困难的理解面向对象,Java对象,什么是真正发生.
更新更新:
这里的争议涉及一个基本的模糊性:究竟在讨论什么?该对象? 或者我们在某种意义上谈论班级本身? 在描述类而不是对象时允许大量的纬度.因此子类不继承私有字段,但作为子类实例的对象肯定包含私有字段.
Nis*_*ant 20
不.私人领域不是继承的......这就是为什么发明了Protected的原因.这是设计的.我想这证明了保护修饰语的存在.
现在来到这里.你继承的意思是什么 - 如果在派生类创建的对象中存在?是的.
如果你的意思是它对派生类有用.好吧,不.
现在,当你进入函数式编程时,超类的私有字段不会以有意义的方式为子类继承.对于子类,超类的私有字段与任何其他类的私有字段相同.
从功能上讲,它不是遗传的.但理想情况是,它是.
好的,只是看看他们引用的Java教程:
超级私人会员
子类不继承其父类的私有成员.但是,如果超类具有访问其私有字段的公共或受保护方法,则子类也可以使用这些方法.
参考:http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html
我同意,那个领域就在那里.但是,子类在该私有字段上没有任何特权.对于子类,私有字段与任何其他类的任何私有字段相同.
我认为这纯粹是观点问题.你可以在任何一方塑造争论.这两种方式都更合理.
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虚拟机规范
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)
我对面试官问题的回答是:私有成员不是在子类中继承的,但只能通过公共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的对象不包含小时和分钟成员,那么事情就搞砸了.
好吧,这是一个非常有趣的问题,我研究了很多并得出结论:超类的私有成员确实在子类的对象中可用(但不可访问)。为了证明这一点,这里是一个包含父类和子类的示例代码,我将子类对象写入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”的私有成员。请告诉我你们的想法。
归档时间: |
|
查看次数: |
205340 次 |
最近记录: |