Topic: 关于继承容易模糊的概念

  Print this page

1.关于继承容易模糊的概念 Copy to clipboard
Posted by: xiaopan
Posted on: 2003-03-18 09:49

JAVA作为面向对象的语言,最重要的的三个概念就是封装、继承、多态。在这里我想对继承中容易模糊的问题做一下补充:
大家在使用继承时,都知道父类中访问修饰符声明为PUBLIC,PROTECT的数据成员和方法可以被子类直接访问,但是PRIVATE的变量和方法就不能被访问,以上的说法其实是不正确的。其实子类通过extends继承了父类,子类会把父类中所有的方法和数据成员作一份拷贝变成自己的东西,无论父类中的声明为什么,PRIVATE修饰的在子类中只是不能被直接使用罢了,如果继承过来的public方法中有使用某个private变量,那么在子类中就能被访问,只是通过继承来的方法罢了。所以说继承是把父类的任何东西都作了一份拷贝在子类中,只是有的可以直接使用,有的不能直接使用。
第二,继承完之后,子类的东西是子类自己的,父类的是父类的,两者之间不会相互影响。比如:父类有一个public int i = 5变量,在子类中通过使用super.i=6会不会把父类的 i 改变为6呢?当然是不会的,子类中的 i 和父类的 i 的关系只是前者是后者的一个拷贝罢了,拷贝晚了之后,其实是没有关系的,不会相互影响;如果在子类中也声明了public int i 又将是什么情况呢? 这时候,在子类中实际上有两个 i 一个是他自己的,另为一个是父类的拷贝,两者是同名同姓的,但是通过this 和 super区分,不会相互混淆。这种情况发生方法就是所谓方法覆盖或重写,但是,实际上子类还是有两个方法(注意是两个),默认使用的覆盖后的方法。

2.Re:关于继承容易模糊的概念 [Re: xiaopan] Copy to clipboard
Posted by: mochow
Posted on: 2003-03-18 14:11

实际上我对于你说的这样的继承是否合理有一定的疑问,主要是你
的例子让人觉得不太合理。

通常的域如果是常量都会设成static的,如果是变量都会设为
属性的形式,把变量设为private,用get和set方法来获取和
修改变量的值。

不知道我这样理解对不对?

3.Re:关于继承容易模糊的概念[RE:MOCHOW] [Re: xiaopan] Copy to clipboard
Posted by: xiaopan
Posted on: 2003-03-18 14:27

我想强调的是即使是PRIVATE变量,子类也是继承的

4.Re:关于继承容易模糊的概念 [Re: xiaopan] Copy to clipboard
Posted by: javaren
Posted on: 2003-03-18 18:48

子类和父类变量如果同名,是变量的隐藏, 子类有两个变量,this.x, super.x
子类和父类方法如果同名,是方法的覆盖, 子类只有一个方法。
例如:
class A {
public String x = "classA";
public void foo() {
System.out.println("A foo");
}
}

class B extends A {
public int x = "classB";
public void foo() {
System.out.println("B foo");
}
public static void main(String[] args) {
System.out.println(this.x);
System.out.println(super.x);
B b = new B();
b.foo();
A a = (A)b;
a.foo();
}
}

结果是:
classB
classA
B foo
B foo

以上结果表明变量存在两个, 而方法只有一个。
子类对象被强制转化为父类型后仍然访问的是子类的方法,因为父类的同名方法被覆盖了,已经不复存在了!

5.Re:关于继承容易模糊的概念 [Re: javaren] Copy to clipboard
Posted by: snowbug
Posted on: 2003-03-18 23:03

javaren wrote:
以上结果表明变量存在两个, 而方法只有一个。
子类对象被强制转化为父类型后仍然访问的是子类的方法,因为父类的同名方法被覆盖了,已经不复存在了!

Actually, the parent method is still accessible inside the direct child class by using the super keyword, such as:

public void method(){
super.method();
}

6.Re:关于继承容易模糊的概念 [Re: snowbug] Copy to clipboard
Posted by: javaren
Posted on: 2003-03-19 13:06

snowbug wrote:
Actually, the parent method is still accessible inside the direct child class by using the super keyword, such as:

public void method(){
super.method();
}


super.method()只在编译期间可见!

7.Re:关于继承容易模糊的概念 [Re: javaren] Copy to clipboard
Posted by: floater
Posted on: 2003-03-19 23:55

javaren wrote:
super.method()只在编译期间可见!

???

8.Re:关于继承容易模糊的概念 [Re: xiaopan] Copy to clipboard
Posted by: javaren
Posted on: 2003-03-20 09:56

我的意思是说,如果子类有跟父类同名的方法(方法的签名一模一样),那么子类的方法将覆盖父类的方法。虽然super.method()可以访问父类的方法,但是super.method()只在编译期间是可见的,就是说,你只能在子类里面另外提供一个方法来实现对父类的方法的间接调用,而不能直接调用父类的方法。我举个例子:
class A {
public String str = "classA";
public void method() {
System.out.println("The Class A's method");
}
}

class B extends A {
public String str = "classB";
public void method() {
System.out.println("The Class B's method");
}
public void callA() {
super.method();
}
}

另外,如果有下面的代码:
B obj = new B();
System.out.println(obj.str); //这里访问的是B类的成员str
obj.method();   //这里访问的是B类的方法method
obj.callA(); //这里访问的是B类的方法callA, 从而达到间接访问A类的方法method
A obj1 = (A) obj; //强制转化成A类对象
System.out.println(obj1.str); //这里访问的是A类的成员str
obj1.method();   //这里访问的是B类的方法method. 这个时候,A类的方法method永远访问不到了!!!

原因分析:B类有跟A类同名的方法, 所以A类的方法method的入口被B类的方法method的入口给覆盖了(编译完成后覆盖!),所以在编译的时候能够通过super.method()找到A.method的入口,从而可以提供对A.method的间接访问,编译完成后,我们就没法找到A.method的入口了,只能访问B类提供的间接访问A.method的方法B.callA来间接的访问A.method. 如果B类不提供这种方法的话,我们就永远也访问不到A.method了。而且就算B类提供了间接访问A.method的方法B.callA, 如果该对象强制转化成A类型,这是B.callA对A类对象来说是不可访问的,所以这时也没法访问A类自己的方法,obj1.method();//这里访问的是B类的方法method. 这个时候,A类的方法method永远访问不到了!!!。

不知道这么说有没有说明白,欢迎大家踊跃讨论。

9.Re:关于继承容易模糊的概念 [Re: javaren] Copy to clipboard
Posted by: floater
Posted on: 2003-03-20 23:36

javaren wrote:
我的意思是说,如果子类有跟父类同名的方法(方法的签名一模一样),那么子类的方法将覆盖父类的方法。虽然super.method()可以访问父类的方法,但是super.method()只在编译期间是可见的,就是说,你只能在子类里面另外提供一个方法来实现对父类的方法的间接调用,而不能直接调用父类的方法。我举个例子:
class A {
public String str = "classA";
public void method() {
System.out.println("The Class A's method");
}
}

class B extends A {
public String str = "classB";
public void method() {
System.out.println("The Class B's method");
}
public void callA() {
super.method();
}
}

另外,如果有下面的代码:
B obj = new B();
System.out.println(obj.str); //这里访问的是B类的成员str
obj.method();   //这里访问的是B类的方法method
obj.callA(); //这里访问的是B类的方法callA, 从而达到间接访问A类的方法method
A obj1 = (A) obj; //强制转化成A类对象
System.out.println(obj1.str); //这里访问的是A类的成员str
obj1.method();   //这里访问的是B类的方法method. 这个时候,A类的方法method永远访问不到了!!!

原因分析:B类有跟A类同名的方法, 所以A类的方法method的入口被B类的方法method的入口给覆盖了(编译完成后覆盖!),所以在编译的时候能够通过super.method()找到A.method的入口,从而可以提供对A.method的间接访问,编译完成后,我们就没法找到A.method的入口了,只能访问B类提供的间接访问A.method的方法B.callA来间接的访问A.method. 如果B类不提供这种方法的话,我们就永远也访问不到A.method了。而且就算B类提供了间接访问A.method的方法B.callA, 如果该对象强制转化成A类型,这是B.callA对A类对象来说是不可访问的,所以这时也没法访问A类自己的方法,obj1.method();//这里访问的是B类的方法method. 这个时候,A类的方法method永远访问不到了!!!。

不知道这么说有没有说明白,欢迎大家踊跃讨论。

Now I see your point. You are right. But this is designed on purpose, I believe. You overwrite that method because you want users to use new methods, otherwise there is no point to overwrite it, just create a new method.


   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923