Java-4-重载多态

来源:互联网 发布:淘宝达人的推荐步骤 编辑:程序博客网 时间:2024/06/01 11:26

Ø 课堂讨论要点:

 

1.重载 (overload)

 

   一个类中,可以存在多个同名的方法。在传统的面向过程的编程语言中,方法名不能雷同,那么一个方法名被使用后,将不能在别的地方被利用,有的时候,一个方法名确实很好用,能够精确表达某个方法的含义,如果不能被重用,就会导致方法名资源的浪费,造成了编程的复杂性

 

   方法名相同,参数不同,则构成方法的重载,系统将根据你在方法调用过程中,所传进来的参数的数据类型,选择并执行对应的方法。

 

   参数不同则构成重载,具体规则如下:

   1. 参数数量不同

   2.  对应参数位置的参数数据类型不同

   

   案例:

int add( int a , int b);      

int add( int a, int b, int c);

int add( int a, double c); 

int add( int a, int d);   

    [参数名不列入重载考虑范围,构成重名]

    void add( int a, int b);

        [返回值不列入重载考虑范围,构成重名]

    Public int add(int a, int b);

        [访问修饰符不列入重载考虑范围,构成重名]

    

编译器本质上是不允许方法重名的,这在面向对象编程语言中也是这样的, 在程序员的呼吁中,编译器的开发者提供了能够名字重复使用的机制,但编译器最终将把方法名做修正,比如:

int add( int a , int b);         à  add_int_int

int add( int a, int b, int c);    à  add_int_int_int

 

继承环境下,子类即可以重写父类方法,也可以重载父类方法。

在本类中,只能重载,如果出现类似重写的效果,即判断为错误,认定为重名。

 

选择题:

1. public class MethodOver {

2. public void setVar (int a, int b, float c) {

3. }

4. }

Which two overload the setVar method? (Choose Two)

A. private void setVar (int a, float c, int b) { }

B. protected void setVar (int a, int b, float c) { }

C. public int setVar (int a, float c, int b) (return a;)

D. public int setVar (int a, int b, float c) (return a;)

E. protected float setVar (int a, int b, float c) (return c;)

 

2. 重写 (override

 

在继承环境下,子类认可父类的行为 (认同和坚持方法的签名),但对行为的具体执行过程不认可,则决定对父亲这个方法进行局部或者完全的更新。

 

重写的模式从内容实现上分为2种:

1) 改良性,补充型重写:对父亲提供的方法内容进行补充。

2) 颠覆性重写:完全否定父亲所提供的方法内容,彻底改写。

 

    重写不是覆盖掉父亲的方法,父亲该方法在子类内部还是存在的。在内存中,体现为子类和父类两个同签名方法共存的现象。在子类方法中,可以通过super.来显示调用父类被重写的方法,如果不用super. ,则表示调用子类的重写方法。

 

    继承环境下子类方法设置的可能情况:

 

     Class A{

      void sayHello(int a, int b)
}

 

Class B extends A

 

     Void sayHello(int a, int b){ //在子类中,出现和父类方法同签名,则为重写

      ........

     }

 

     Void tellYouSomething(int a){ //方法名和所有父类方法均不同,称为子类自定义新方法

     

     }

 

     Void sayHello(int a, int b, int c){ //子类对父类方法的签名做部分改造,叫做跨类重载

  

     }

   

    3. 多态 (polymorphism)

    

a. 多态三要素

1) 在继承环境下,子类重写父类方法。

2) 通过父类引用变量指向子类对象。

3) 恰好通过父类引用变量调用的是被重写的方法。

       

       在此情况下,将发生多态效应,从常态来说,通过父类引用变量指向子类对象,该引用变量只能看到子类对象中的父类部分,不可能调用到子类方法。但是由于这里存在重写,通过父类引用变量向子类对象发送信号的时候,该方法调用信号由于和子类重写方法签名是完全一致,结果调用子类的该重写方法,对于方法的主调者来说,其并不知道会产生这个结果,纯属意外。

 

b. 多态的用途

为今后编写框架代码提供了可能,适合用来编写通用底层代码。

 

    public static void main(String[] args) {

Mouse mouse=new Mouse();

Tiger tiger=new Tiger();

//mouse.sound();

//tiger.sound();

//Animal a=new Tiger();

//a.sound();

letAnimalSound(new Tiger());

letAnimalSound(new Mouse());

letAnimalSound(new Sheep());

 

   }

    static void letAnimalSound(Animal a){

  a.sound();

}

 

4. 不定参数 (…)

 double add(int a, int b, double... m){

 double sum=a+b;

 

 for(int i=0;i<m.length;i++)

 sum=sum+m[i];

 

 return sum;

 

}

 

不定参数是为了方便参数数量不确定的情况,以提高方法签名的高度兼容性。

M最终将会被理解为 double[], 

 

一个方法签名的不定参数只能有一个,而且是最后一个。

 

int add(int ... n){

 

 int sum=0;

 

 for(int x:n)   //for…each循环

sum=sum+x;

 

 return sum;

 }

 

   3. 抽象类 (abstract class

 

    类是模具,有了类,就可以生产对象。

   

如果一个模具,计划有10个功能,但最终仍然有2个功能没有被实现,这个模具不能用于生产。

 

  同理,类也有类似的现象,有3个方法,实现了2个, 有1个还没实现,但方法签名已经计划好了这个未实现的方法,必须用abstract来修饰,以通知系统本方法未实现,否则无法通过编译,该方法为抽象方法,拥有一个或者多个抽象方法的类,叫做抽象类。

 

抽象类是未完工的类,其不能用于生产实例!

 

创建实例       创建子类(继承)     作为引用变量数据类型

普通类         Yes             Yes                  Yes

Final类         Yes             No                  Yes

abstract类       no             Yes                  Yes

 

抽象类可以被继承,而且渴望被继承 (愚公移山的故事)

 

子类继承父类,实现了父类的所有抽象方法,该子类可以脱掉抽象的帽子,成为普通类,也称可实例化类;否则,如果不实现父类抽象方法,则无论子类自身方法规模多么庞大,也无法忽视内部有一个抽象方法的事实,子类是不完整的,这个不完整是父类带来的,父类是子类的一部分,所以子类也还是抽象类,不能实例化。

 

抽象类语法识别注意点:

a. abstract void method3(){ };  //已经实现了,不能再说是抽象,这是矛盾的。

b. void method3( ) { };  // 请注意,空实现也是实现。

 

以上内容是抽象类的语法解释。下面讲解下抽象类的含义:

1) 被动抽象类

    因为一个类的体内有抽象方法,该类不得不用抽象来修饰。

 

2) 主动抽象类

一个类所有方法都实现了,是可实例化类,其故意主动地声明自己是抽象类。

一个类的作者为了不让使用者去创建这个类的实例,其故意申明此类为抽象类。

比如: Animal , Shape, ValueObject…..

该类作者认为这个类是一个抽象的概念,没有创建实例的意义,该类需要被继承,然后创建子类实例才有意义。

 

任何一个类,无论是否有抽象方法,都可以abstract来修饰。

 

(例外:

不能用abstract来修饰已经用final修饰的类

     Abstract类渴望被继承,而final拒绝继承,两者构成反义关系,不能同时存在,否则就构成了矛盾。

What will happen when you attempt to compile and run this code?

abstract class Base{

abstract public void myfunc() {};

public void another(){

System.out.println("Another method");

}

}

public class Abs extends Base{

public static void main(String argv[]){

Base b= new Abs(); //A

b. myfunc(); //B

}

public void myfunc(){

System.out.println("My Func");

}

public void amethod(){

myfunc();

}

}

[1 choice]

1) The code will compile and run, printing out the words "My Func"

2) The compiler will complain error at //A.

3) The compiler will complain error at //B.

4) The compiler will complain error at other position.

 

4. 接口 (interface)

 

   一个抽象类,所有的方法都是抽象的,所有方法的public, 我们把这样的类叫做极度抽象类,是最干瘪的类。

   

public abstract class A {

public abstract void method1();

public abstract void method2();

public abstract void method3();

}

 

public interface A {

void method1();

void method2();

void method3();

}

   

极度抽象类可以缩写为接口。那么,所有接口的方法都是public abstract.

 

 

类创建的过程

接口 (interface)  à  abstract class  à  可实例化类

 

创建实例       创建子类(继承)     作为引用变量数据类型

普通类         Yes             Yes                  Yes

Final类         Yes             No                  Yes

abstract类     no              Yes                  Yes

接口           no              yes                   yes

 

接口创建子类:

 1. Extends        继承了接口,而得到结果还是接口。

      一个类没有实现接口方法的计划,而是想继续增加接口方法,必须使用extends关键字来表示继承。

 2.   implements    

      一个类如果有对接口方法做实现的计划,必须使用implements关键字来继承接口。

 

接口是一个特殊的类,一个类实现了接口,最终成为可实例化类,那么类必须包含接口中所定义的所有方法。

 

一个接口引用变量可以指向一个实现了这个接口的类对象,但只能调用这个对象中接口部分。

 

接口的用途:

 

  现实生活中,没有血缘的对象之间往往有共同的行为和动作,但每个对象的行为和动作的具体内容是不一样的,比如士兵, 每个士兵都是射击,擒拿格斗等行为,但有的人是神枪手,而有的老是不及格,那么也就是说大家都有这个动作,但动作的实现个人各自不同。

   以上是现实生活中的具体情况,为了更好的模拟现实生活,语言必须演化,来满足这个要求,极度抽象类在语法层面上满足了这样要求,被重视起来,并最终得到了一个新的名字,接口。

   

接口在某种程度上与多态有同样的效果,能够写出可高度复用的代码。

 

5. 访问修饰符 (access modifier)

 

   现实生活中,一个人有很多属性, 其不会把所有的属性都告诉任何人,而是有选择性对外说明,起到一个自我保护的作用,这也是算是一种“封装”。

   根据软件模拟现实的原则,语言设计者推出了访问修饰符这个机制来实现封装。

   

a. 从继承角度谈访问修饰符

                       本类          同包子类         异包子类

Private                 yes            no             no

<package>            yes            yes             no

Protected              yes            yes             yes

Public                  yes            yes             yes

 

<package>修饰符只有本包内部类可见,外部类,即使是子类也看不到。

Protected 修饰符不仅本包内部可见,外包子类也可见。

 

b. 从引用角度谈访问修饰符

               本类   同包子类   同包非子类  异包子类   异包非子类

Private        yes     no          no         no        no

<package>   yes     yes          yes        no        no

Protected     yes     yes          yes        no        no

Public        yes      yes          yes        yes       yes

 

Assume that country is set for each class.

Given:

10. public class Money {

11. private String country, name;

12. public  String getCountry() { return country; }

13.}

and:

24. class Yen extends Money {

25. public String getCountry() { return super.country; }

26. }

27.

28. class Euro extends Money {

29. public String getCountry(String timeZone) {

30. return super.getCountry();

31. }

32. }

Which two are correct? (Choose two.)   答案:BE

A. Yen returns correct values.

B. Euro returns correct values.

C. An exception is thrown at runtime.

D. Yen and Euro both return correct values.

E. Compilation fails because of an error at line 25.

F. Compilation fails because of an error at line 30.

 

6. javabean

 

a. 广义javabean的概念

   任何一个构成java应用程序的class文件,都叫javabean.

 

b. 狭义javabean概念

   

Ø 封装 (encapsulation)

为了保护一个类的属性不被外界直接访问,保护隐私,我们经常把属性设置成私有,并配套两个getter/setter方法对其进行匹配访问。

 

   userName à  getUserName() , setUserName()

 

一个java类, 所有的属性均为私有,每个属性配套一对getter/setter方法进行属性的访问,同时该类还有一个无参构造方法,符合以上条件书写的类,被称为javabean.

0 0
原创粉丝点击