Java开发网 Java开发网
注册 | 登录 | 帮助 | 搜索 | 排行榜 | 发帖统计  

您没有登录

» Java开发网 » Java SE 综合讨论区 » Java与OOP初步  

按打印兼容模式打印这个话题 打印话题    把这个话题寄给朋友 寄给朋友    该主题的所有更新都将Email到你的邮箱 订阅主题
flat modethreaded modego to previous topicgo to next topicgo to back
作者 [原创]Java中多态变量的讨论和总结
jimshen





发贴: 18
积分: 2
于 2006-08-08 06:04 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
一、多态的表现形式

多态的表现形式有方法重载,方法改写,多态变量和泛型。重载是一种静态的多态性,在程序编译时确定被调用的方法,称为早绑定。而多态变量和改写相结合之后,方法的调用在运行时才能确定,是动态的多态性,称为晚绑定。

二、里氏替换原则(The Liskov Principle of Substitution)

在静态类型语言中,在父类和子类之间的关系存在下面的现象:

子类的实例必须拥有父类的所有数据成员;
子类的实例必须至少通过继承(如果不是显示地改写)实现父类所定义的所有功能;
这样,在某种条件下,如果用子类实例来替换父类实例,那么将会发现子类实例可以完全模拟父类的行为,二者毫无差别;
替换原则是指如果有A和B两个类,类B是类A的子类,那么在任何情况下都可以用类B来替换类A,而外界则毫无察觉。

不是所有继承产生的子类都符合替换原则,符合替换原则的子类称为子类型。

三、静态类型和动态类型

在静态类型面向对象语言中,一个变量所存储的值的类型并不等同于这个变量所声明的类型。声明为父类类型的变量可以包含子类的实例值。

静态类型是指变量在声明时所确定的类型,并且一经声明就不会改变;动态类型是指这个变量实际存储的值的类型。在静态类型的面向对象程序设计语言中,在编译时消息传递表达式的合法性不是基于接收器的动态类型,而是基于接收器的静态类型。而对象对消息的响应取决于对象的动态类型。

这样的变量在多态中称为多态变量。

考虑下面的类图:


对应的程序如下:

class SuperClass {
  public int x;
  public void f1() {
  }
  public void f2() {
  }
}
class SubClass extends SuperClass{
  public int y;
  public void f1() {
  }
  public void f3() {
  }
}
public class Test{
  public static void main(String[] args){
    SuperClass ob=new SuperClass(); //(1)
    ob=new SubClass(); //(2)
    ob.x=1; //(3)
    ob.y=2; //(4)
    ob.f1(); //(5)
    ob.f2(); //(6)
    ob.f3(); //(7)
  }
}

程序中,子类改写了父类中的f1()方法,添加了自己的属性y和方法f3()。语句(1)中变量ob的静态类型是SuperClass,动态类型是SuperClass;语句(2)中变量ob的静态类型不变,动态类型是SubClass(子类类型),子类对象的地址可以存放在父类类型的引用变量中,即父类引用变量引用子类对象;(3)、(5)、(6)是正确的,(4)、(7)是错误的,因为对于引用的合法性依赖于变量的静态类型,属性y和方法f3()在SuperClass中不存在,故有错,还应该注意参数的匹配;(5)调用的f1()是子类的f1(),(6)调用的f2()是父类的f2(),这是因为对于消息的响应取决于变量的动态类型,因此f1()是SubClass中的f1()。
如果在父类和子类中存在属性的覆盖,则通过ob(父类对象名)访问的x是父类中被覆盖的属性。

class SuperClass {
  public int x=1;
  public void f1() {
  }
  public void f2() {
  }
}
class SubClass extends SuperClass{
public int x=2;
  public int y;
  public void f1() {
  }
  public void f3() {
  }
}
class Test{
  public static void main(String[] args){
    SuperClass ob=new SuperClass(); //(1)
    ob=new SubClass(); //(2)
System.out.println(ob.x);
    ob.f1(); //(5)
    ob.f2(); //(6)
  }
}

四、父类对象和子类对象

子类从父类继承了所有的属性和方法,因此作用在父类上的方法应用在子类对象上也是合法的。由于继承表达的是一种is a关系,即子类对象可以被视为父类的一个对象,因此可以把子类对象的引用赋给父类对象;反之,父类对象不一定是其某个特定子类的对象,因此不一定满足is a关系,因此不能把父类对象的引用直接赋给子类对象。

class Employee {
private String name;
private int salary;

Employee(String name,int salary){
  this.name=name;
  this.salary=salary;
}

public String getDetails() {
  return Name: " + name + "\nSalary: " + salary;
}
}

class Manager extends Employee {
String department;

Manager(String name,int salary,String department){
  super(name,salary);
  this.department=department;
}

public String getDetails() {
  return super.getDetails() + "\nDepartment: " + department;
}
}

public class Test{
public static void main(String args[]){
  Employee a=new Employee("Mike",800);
  Manager b=new Manager("Tom",1200,"Research");
  Manager c=a; //Error
  Employee d=b; //True
  System.out.println(A.getDetails());
  System.out.println(D.getDetails());
}
}

根据消息传递的概念,对消息的响应取决于接收器。而这又依赖于接收器的动态类型。因此,当父类对象中存放了子类对象的引用,并且父类和子类中有方法覆盖时,通过父类对象将会调用子类中的方法。

同时,在编译时消息传递表达式的合法性不是基于接收器的动态类型,而是基于接收器的静态类型。因此,当父类对象中存放了子类对象的引用时,不能通过父类对象名引用子类中新定义的成员(包括属性和方法)。例如,下面的语句是错误的:

System.out.println(d.department);

可以通过强制类型转换把父类对象转换成子类对象,然后再进行访问:

Manager e=(Manager) d;
System.out.println(e.department);

五、运行时类型识别和向下造型

替换原则将数据的类型从子类提升到了父类。有时也需要做相反的事情,例如判断父类对象所存放的值是否是某个子类的对象。

类型的强制类型转换只能用于子类唯一这种确定的情况下,如果子类不止一个,则可能发生错误,可以通过instanceof运算符来识别子类对象所属的类。

public class Manager extends Employee
public class Contractor extends Employee

假设有一个子类对象,可以通过下面的语句来判断它所述的类并执行相应的操作:

if(a instanceof Manager){
Manager b=(Manager) a;
......
}
else if(a instance of Contractor){
Contractor b=(Contractor) a;
......
}

例如在上面的操作中,可以把a这个父类对象转换成相应的子类对象,从而去访问子类中新增的属性或方法,这称为向下造型(down casting)。造型(cast)也就是通常所说的类型转换。类型的提升称为向上造型(up casting)。

六、多态和抽象类、抽象方法

抽象类不能实例化,但是可以声明抽象类的变量用以存放其子类对象的引用。另外,抽象方法为其子类规定了一个必须实现的接口,这样在多个子类中就拥有一个相同的接口方法。

在程序中可以定义一个父类的数组用于保存所有子类的对象,从而保持程序的简洁和灵活性。下面的程序说明了这个问题。


abstract class Shape{
public abstract void draw();
}
class Circle extends Shape{
private int x;
private int y;
private int radius;
public Circle(int x,int y,int radius){
this.x=x;
this.y=y;
this.radius=radius;
}
public void draw() {
System.out.println("draw circle: ("+x+","+y+"),radius="+radius);
}
}
class Line extends Shape{
  private int x1,y1,x2,y2;
  public Line(int x1,int y1,int x2,int y2){
    this.x1=x1;
    this.x2=x2;
    this.y1=y1;
    this.y2=y2;
  }
  public void draw(){
    System.out.println("draw line,("+x1+","+y1+")-("+x2+","+y2+")");
  }
}
public class TestShape{
  public static void main(String[] args){
    Shape[] s=new Shape[4];
    s[0]=new Circle(1,1,10);
    s[1]=new Line(3,4,20,12);
    s[2]=new Circle(3,10,20);
    for(int i=0;i<s.length;i++){
      if(s[i]!=null)
        s[i].draw();
    }
  }
}

如果没有多态这个特性或者不利用多态这个特性,则程序将复杂得多。

Java中所有的类的最终根类是java.lang.Object,因此可以Object类型的引用变量可以存放所有Java对象的引用,也使用一个Object数组保存Java中所有的对象。


jimshen edited on 2006-08-08 06:29

作者 Re:[原创]Java中多态变量的讨论和总结 [Re:jimshen]
jimshen





发贴: 18
积分: 2
于 2006-08-08 06:30 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
一个帖子只能有一个附件?

附件为对应的ppt(推荐,里边有更加清晰的例子)和对应的代码

ppt.rar (99.92k)



作者 Re:[原创]Java中多态变量的讨论和总结 [Re:jimshen]
jimshen





发贴: 18
积分: 2
于 2006-08-08 06:36 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
ppt中的几个页面截图







作者 Re:[原创]Java中多态变量的讨论和总结 [Re:jimshen]
jameszhang



CJSDN高级会员


发贴: 1594
积分: 111
于 2006-08-08 19:52 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
写的不错 ,其中 动态多态 不讨论 语言,我 认为 就是由 继承关系 而生的


"First they ignore u, then they laugh at u, then they fight u, then u will win

Mahatma Gandhi"

作者 Re:[原创]Java中多态变量的讨论和总结 [Re:jimshen]
jimshen





发贴: 18
积分: 2
于 2006-08-08 21:50 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
"动态多态 不讨论 语言" 是什么意思?


作者 Re:[原创]Java中多态变量的讨论和总结 [Re:jimshen]
Java9





发贴: 1
积分: 0
于 2006-08-17 13:00 user profilesend a private message to usersearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
ppt怎么不能下载呢?
哪位能重新发一份呀,谢谢!




flat modethreaded modego to previous topicgo to next topicgo to back
  已读帖子
  新的帖子
  被删除的帖子
Jump to the top of page

   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