数据成员,方法,继承,多态
2006-12-13 00:03
190 查看
面向对象的方法中,继承和多态是非常重要,也是非常好用的一个特性,理解和掌握这种特性是必须的。
多态的表现可以从两个大的方面来体现:1)由重载和覆盖造成的多态;2)在父类调用子类的过程中体现的多态。
第一类多态比较好理解,总的都可以看成是后面的方法和对象覆盖前面的方法和对象。这种覆盖包括类的数据成员和方法。比如,子类定义的数据和方法可以覆盖父类定义的数据和方法,同名的方法由于不同参数的调用造成的多态。如果子类要调用父类的成员和方法,必须经过super关键字来明确地引用。在super的用法上,Java与C++相比的一个不足是其引用只能对直接父辈进行,而对于祖父辈的成员和方法,则没有C++的由“类名::成员或方法名”的手段。
而从父辈动态地引用子辈的数据和方法,其实能能够体现多态的奇妙,也是一种更为好用的多态。因为现实中可能往往有这类的需求,比如我们定义了一个移动物的公共的基类,其中定义了一个公共的“移动”方法和公共的“速度”数据。而移动物可以派生出人、汽车、飞机等类,其速度和移动方法都在这些派生类中实现和赋值。则我们可能希望在某个函数中通过使用移动物类的移动方法和速度数据来在运行时动态的引用具体正确的方法和数据,或者我们希望在移动物类中直接使用其派生类的移动方法和速度数据。这种需求的实现能够极大地方便我们的编程。
在C++中,通过对父类的函数指定其为visual虚拟函数,即可以实现通过父类对象引用派生类对应的函数,而没有指定visual的函数则不具这种多态性。而Java中,所有的方法都具有这种虚函数的特性。如下所示:
class A {
public String d="A";
public void print() {
System.out.println(d);
}
public void com() {
print();
}
}
class B extends A{
public String d="B";
public void print() {
System.out.println(d);
}
}
class C extends B {
public String d="C";
}
定义了一个重载的方法print(),并且在类A中还定义了一个公共接口性函数com(),其中调用方法print()。则如下的程序由于父辈调用子辈的类似于C++虚函数特性的多态具有下面的结果:
public class test {
public static void use(A a) {
a.print();
}
public static void main(String[] args) {
A a=new A();
B b=new B();
C c=new C();
a.com();
b.com();
c.com();
use(a);
use(b);
use(c);
}
}
其运行结果为:A B B A B B
从结果看,不管是通过类A内部的定义中的方法com,还是通过在外部定义的以基类A为参数,并通过参数引用其方法print的函数use中,通过基类对象我们都正确地引用了子类的对应方法。这里我们还需要注意从B派生出来的类C,由于没有派生相应的方法print,所以实际调用的是继承层次中最后的一个print。
但是对于继承层次中的数据成员,则没有这种从父类访问子类的多态机制。这里,如果我们修改use函数如下:
public static void use(A a) {
System.out.println(a.d);
}
则运行结果为:A B B A A A
其原因是因为在函数中直接引用a的数据成员,这种试图通过基类对象引用子类对象的数据成员是不行的,因为在参数传递时,实例b和c已经被转换为类A,而虽然可以通过A的对象引用B和C重载的方法,但是是不能够直接引用B和C的数据成员的。如果想要实现这种效果,可能唯一的方法是直接传递相应的数据成员来完成,而试图通过传递类的实例来完成时不行的。如,可以在类A中添加如下的静态方法:
public static void prtD(String s) {
System.out.println(s);
}
然后进行如下的调用:
A.prtD(a.d);
A.prtD(b.d);
A.prtD(c.d);
则可以得到正确的结果:A B C
多态的表现可以从两个大的方面来体现:1)由重载和覆盖造成的多态;2)在父类调用子类的过程中体现的多态。
第一类多态比较好理解,总的都可以看成是后面的方法和对象覆盖前面的方法和对象。这种覆盖包括类的数据成员和方法。比如,子类定义的数据和方法可以覆盖父类定义的数据和方法,同名的方法由于不同参数的调用造成的多态。如果子类要调用父类的成员和方法,必须经过super关键字来明确地引用。在super的用法上,Java与C++相比的一个不足是其引用只能对直接父辈进行,而对于祖父辈的成员和方法,则没有C++的由“类名::成员或方法名”的手段。
而从父辈动态地引用子辈的数据和方法,其实能能够体现多态的奇妙,也是一种更为好用的多态。因为现实中可能往往有这类的需求,比如我们定义了一个移动物的公共的基类,其中定义了一个公共的“移动”方法和公共的“速度”数据。而移动物可以派生出人、汽车、飞机等类,其速度和移动方法都在这些派生类中实现和赋值。则我们可能希望在某个函数中通过使用移动物类的移动方法和速度数据来在运行时动态的引用具体正确的方法和数据,或者我们希望在移动物类中直接使用其派生类的移动方法和速度数据。这种需求的实现能够极大地方便我们的编程。
在C++中,通过对父类的函数指定其为visual虚拟函数,即可以实现通过父类对象引用派生类对应的函数,而没有指定visual的函数则不具这种多态性。而Java中,所有的方法都具有这种虚函数的特性。如下所示:
class A {
public String d="A";
public void print() {
System.out.println(d);
}
public void com() {
print();
}
}
class B extends A{
public String d="B";
public void print() {
System.out.println(d);
}
}
class C extends B {
public String d="C";
}
定义了一个重载的方法print(),并且在类A中还定义了一个公共接口性函数com(),其中调用方法print()。则如下的程序由于父辈调用子辈的类似于C++虚函数特性的多态具有下面的结果:
public class test {
public static void use(A a) {
a.print();
}
public static void main(String[] args) {
A a=new A();
B b=new B();
C c=new C();
a.com();
b.com();
c.com();
use(a);
use(b);
use(c);
}
}
其运行结果为:A B B A B B
从结果看,不管是通过类A内部的定义中的方法com,还是通过在外部定义的以基类A为参数,并通过参数引用其方法print的函数use中,通过基类对象我们都正确地引用了子类的对应方法。这里我们还需要注意从B派生出来的类C,由于没有派生相应的方法print,所以实际调用的是继承层次中最后的一个print。
但是对于继承层次中的数据成员,则没有这种从父类访问子类的多态机制。这里,如果我们修改use函数如下:
public static void use(A a) {
System.out.println(a.d);
}
则运行结果为:A B B A A A
其原因是因为在函数中直接引用a的数据成员,这种试图通过基类对象引用子类对象的数据成员是不行的,因为在参数传递时,实例b和c已经被转换为类A,而虽然可以通过A的对象引用B和C重载的方法,但是是不能够直接引用B和C的数据成员的。如果想要实现这种效果,可能唯一的方法是直接传递相应的数据成员来完成,而试图通过传递类的实例来完成时不行的。如,可以在类A中添加如下的静态方法:
public static void prtD(String s) {
System.out.println(s);
}
然后进行如下的调用:
A.prtD(a.d);
A.prtD(b.d);
A.prtD(c.d);
则可以得到正确的结果:A B C
相关文章推荐
- java继承时多态方法与成员的访问
- C#基础知识复习1代码规范-执行流程(c#)-面向对象-引用命名空间-封装-继承-访问修饰符-虚方法-静态成员-多态-抽象类等
- javascript:类,成员变量,成员函数,类变量,类方法,继承,多态
- protected数据和方法----继承和多态
- 7.1面向对象(继承中成员方法关系,final关键字,多态,抽象类,接口)
- 图解Java多态内存分配以及多态中成员方法的特点
- 关于C#中静态数据成员和静态方法的总结。
- Java反射高级应用--利用反射调用类的私有方法修改私有方法值,以及替换Java的类成员数据
- 图解Java多态内存分配以及多态中成员方法的特点
- 继承之成员方法成员变量之爸爸偷钱
- 《java编程思想》之控制对成员的访问权限的原因、final、继承和组合、私有方法的“覆盖”
- 类的静态数据成员的继承
- Java基础02 方法与数据成员
- 备忘,override,new,抽象方法,继承多态等
- Java基础教程之对象的方法与数据成员
- C#多重继承 + 多态 + 扩展方法 简单示例
- 谈一谈多态忠成员变量,方法问题
- 私有数据成员的继承问题
- 编写一个矩形类,私有数据成员为矩形的长( len)和宽(wid),wid设置为0,有参构造函数设置和的值,另外,类还包括矩形的周长、求面积、取矩形的长度、取矩形的长度、取矩形的宽度、修改矩形的长度和宽度为对应的形参值等公用方法。
- 封装 继承 多态 方法重载,方法覆盖