java多态



       提到java的多态,想必是很多java新手一个较难跳跃的坎。
         下面,我将自己理解的多态在这里给总结下。
         多态,分为编译时的多态和运行时多态。
         1.编译时的多态。
         首先,说到一个科学概念的时候,我们应该清楚,这个概念只是描述了一种现象或者         规律的一个抽象词汇,所以我们应该做的是,去查找这个概念真正描述的现象。
         什么是编译时的多态呢?
         其实说白了,就是方法的重载,这种现象就体现了编译时的多态,是面向对象语言的         多态的一种体现。但,它是编译时的多态,后面会说运行时多态。
         就是说,编译器在编译的时候,它会自己去判断,调用哪一个重载的方法。这种机制          ,就体现了多态,而不需要人为的去指定。
         编译器,会自动的根据,方法的参数的个数,类型,自动的调用对应的方法,而不需         要人为的干预,这种现象就体现了多态。
         这种多态一个简单的例子就是

void println(int i){};

     void println(float i){};
     void println(string str){};
          这三个方法在调用的时候,编译器的自动选择,就体现了多态,这种多态比较简单,这里就不再多做解释了。

         2.运行时的多态

          说到运行时的多态,当然还是要去看,什么样的现象我们把它称为多态呢?

          这样一种现象我们把它称为多态:

         

class Employee{
void getDetail(){
     System.out.println("is a Employee");
     }
}
class Manager extends Employee{
void getDetail(){
     System.out.println("is a Manager!");
     }
void getDepartment(){}
}
class Secretary extends Employee{
void getDetail(){
     System.out.println("is a Secretary");
     }
void getSalary(){}
}

//下面那个静态的方法的调用体现了多态。
public class test{
static void getDetails(Employee e){
e.getDetail();
}
public static void main(String[] args){
Manager e= new Manager();
Secretary e1= new Secretary();
Employee e2= new Employee();
  //下面的三个函数的调用体现了多态
  getDetails(e);
  getDetails(e1);
  getDetails(e2);
 }
}
如上面注释中所示,那三个函数就体现了多态这种现象。

        就是说,子类的对象也是父类的对象,我们在用函数调用的时候,如果定义这个函数接口是父类这种类型的,那么所有重写了父类的那些方法的子类,都可以作为这个函数的参数,函数在编译的时候,并不知道,这个参数到底是父类的还是子类的,具体的类型它并不清楚,只有当运行的时候,实实在在的调用的时候,系统会自动的判别是哪种类型,而程序员不用管到底是谁。

        看了这种现象之后,很显然的会有很多的疑问在里面。

        疑问一:

       传过来的那个参数,如果是该类型的子类,那么这个转化合法吗?转换的机理又是什么?

       答:如果传进去的参数是子类,会将子类“上溯造型”,将该变量自动转换为父类那种类型。

         那么什么叫上溯造型呢?

        就是将子类的对象的引用,转换成父类对象的类型的引用,体现了造型,又因为上从下到上的一级转化,又体现了向上,综上可知叫做上溯造型。

      疑问二:

     你怎么知道传进来的那个类型,这个类中会有要调用的那个方法呢?

      答:请看我们多态现象下面的解释,就是说,要实现多态,必须是子类当中重写了父类的方法,这样就可以实现不用管类型,到时候调用的时候运行时自动检测。

     如果深入的理解的话,这个问题其实还要说到,上溯造型上,一般课本讲述的时候,会先讲述上溯造型,这里我们是先看多态这个现象,然后看上溯造型,所有这点有点不好理解。

      其实呢,本质上,那个传值的过程就是个上溯造型的过程,如Employee e=e1//e1=new manager();就是说,把e1上溯造型为Employee类型的,下面说下上溯造型一些要点。

      上溯造型:

      把子类的对象的引用,转化为父类类型的变量,那么这个变量就属于父类类型了。

     注意:

     1.该变量可以调用父类中所有的方法成员。

     2.该变量还可以调用子类中重写了父类的方法。

     3.该变量不可以调用子类中特有的方法。

注意的三点,很好理解,因为这个变量已经造型为父类类型,那么它就不可以随随便便的调用子类的东西了,它只能要么调用父类中的东西,要么调用父类和子类的共有的东西,反正就是它属于父类,它可以调用父类所有东西,包括哪些被子类重写了的方法,我们多态就是体现在那些被子类重写了的方法上,就是特别的该变量在调用重写的那些方法时,系统怎么判断该调用谁呢?是父类的呢?还是子类的呢?就看运行时这个变量是谁了。这就是多态。

         疑问三:

       上溯造型可以调用重写的方法,那么那些子类中特有的成员变量被隐藏,那么在多态时候,我如果想调用那些子类的特有的东西的时候该怎么办呢?

      答:问的好!我们在多态的时候引用,子类特有的成员呢?ok

         我们的强制类型转换应运而生,我们来看看啥是强制类型转换呢?

           强制类型转换:

        通俗的说,就是把一个对象类型转化为另一个对象类型。(有点像,一般的类型转换机制,但是它又有所自己的限制)

      限制:

     1、这些类必须之间有继承关系,无关系者不能乱转化。

     2.目标对象类型一定是当前转化类型的子类,否则就是上溯造型了,不需要强制转化。

     其实呢,这个强制转化是与上溯造型,是同生共死的,就是说,有了上溯造型必然有强制转化,这样为我们多态是访问子类的特有成员,提供方便,不然全是访问的共有的。

     所以说,在多态的时候,很多时候,我们会用到强制类型转化,去访问子类的特有成员。

      疑问四:

      说了这么多,这个强制类型到底杂用啊?来个实例看看。。

   好吧!

  下面上实例

     

static void getDetails(Employee e){
if(e instanceof Manager){
Manager m = (Manager)e;
m.getDepartment();
}
e.getDetail();
}
上面的这个方法中,加了一些东西

instanceof 是个关键字,作用是检测,左边的变量是否是右边类型的引用。

第三行,进行强制类型转换,

第四行,调用子类特有的方法。

下面都相同。

说了这么多,这些东西都是联系在一起的,先辅相成的,所以不要把上溯造型和,多态,强制类型割裂开来。


       下面附上课上老师的讲义,好好琢磨下那几个类,差不多都理解了。
// ------------------------
public class pa {
  public static void main(String[] args){
    Employee emp = new Employee("zhao",28,500.0F);
    Manager  mgr = new Manager("xu",35,800.0F,200.0F);
    Director dor = new Director("huang",45,1000.0F,500.0F,"2222","d01");
    System.out.println(emp.getInfo());
    System.out.println(mgr.getInfo());
    System.out.println(dor.getInfo());
    System.out.println();
  }
}

class Employee {
  String  name ;
  int  age ;
  float  salary = 300 ;

  Employee(String n,int a,float s){
    name = n ;
    if(a>=18 && a<=60) age = a ;
     else {System.out.println("illegal age");
           System.exit(1); }
    salary = s;
  }
  
  Employee( String n , int a ) {
    this(n ,a ,300 ) ;   
 }
  void  upSalary(float inc) {
    salary = salary + inc ;
  }
  String getInfo() {
    return "employee :" + name + "\t" + "salary: " + salary ;
  }
}

class  Manager extends Employee {
   float  allowance;
   Manager(String n,int a,float s , float aa){
     super(n,a,s);
     allowance = aa ;
   }
   void setAllowance(float a) {
     allowance = a ;
   }
  String getInfo() {
    return super.getInfo() + "\t" + "allowance :" + allowance ;
   }
}
class Director extends  Manager {
   String  telephone  ;
   String  department ;
   Director(String n,int a,float s,float aa,String tel,String dep){
     super(n,a,s,aa);
     telephone = tel ;
     department = dep;
   }
   void setTel(String tel) {
     telephone = tel ;
   }
   String getInfo() {
     return name + "  is the management of " + department ;
   }
}
//------------------多态--------------
class pb {
  public static void main(String[] args){
    Employee e1 = new Employee("wang1",30,500);
    Employee e2 = new Manager("wang2",40,800,200);
    Employee e3 = new Director("wang3",50,1000,500,"3333","d02");
    if(e2 instanceof Director)System.out.println("e2 is a Director class!");
    else System.out.println("e2 is Manager!");
    System.out.println(e2.name);
 //   System.out.println(e2.allowance);
    
    e2.upSalary(200.0F);
 //   e2.setAllowance(500.0F) ;
    

    e3.age = 55 ; 
//    e3.department = "d03";
    
    e3.upSalary(500);
  //  e3.setTel("8888");
    

    System.out.println(e1.getInfo());
    e2 = new Employee("wang122",30,500);
    System.out.println(e2.getInfo());
    System.out.println(e3.getInfo());
  }
}

//----------------up cast  -------------------

class pc {
  public static void main(String[] args){
    Director d = new Director("Jack",45,1000.0F,500.0F,"4444","d03");;

    Manager m =d ;     // need? Manger m = (Manger)d
    d.setAllowance(500);
    if(m instanceof Director)System.out.println("m is a Director");
    else System.out.println("m is a Manager");
    System.out.println(m.getInfo());
    System.out.println();
  //  m.setTel("2222");         
    
    Employee e = d ;          // need? Employee e = (Employee)d
    e.upSalary(1000.0F) ;
    System.out.println(e.getInfo());
  }
}

//-----------------down cast--------------------

class pd {
  public static void main(String[] args){
    Employee e1 = new Employee("Tom",30,500);
 //   Manager m1 = e1;            
//    Manager m2 = (Manager)e1;    

    Employee e2 = new Director("Bob",50,1000,500,"5555","d04");
    if (e2 instanceof Employee) {
      //System.out.println( (Director)(e2)).telephone);
      System.out.println("e2 is a Employee!");
      Director d = (Director)e2 ;
      d.setTel("9999");
      d.department="d05";
      System.out.println(d.getInfo());
    }
  }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值