多态

多态见于有继承层次的类结构中。由以下代码所示,可知

1. public权限的方法有多态性,静态方法和成员变量没有多态性

1)将子类对象可以赋给父类引用,这样调用对象的方法时会动态绑定具体的对象,父类中所有和子类中同名的public方法会被子类覆盖,当调用此类时调用的即为子类中的方法,如调用dynamivGet()方法时实际调用的是子类中的方法。但是像privateGet这样的private方法则不会被子类覆盖,在父类中的构造函数中调用privateGet方法即为父类中定义的方法。

2)静态方法不具有多态性,因为静态方法是和类绑定的,不是和对象绑定的(静态方法输出的内容取父类还是子类并不取决于创建对象的类型,而是取决于所定义变量的类型)。只有类中的方法才有多态的概念,类中成员没有多态的概念。

3)成员变量是没有办法实现多态的,成员变量的值取父类还是子类并不取决于创建对象的类型,而是取决于所定义变量的类型,这是在编译期确定的。如System.out.println("sup.i= "+sup.i);和System.out.println("sub.i ="+sub.i);两行的输出所示。

package java20160111;
/**
 * 验证子类中对父类中同名的成员变量、静态方法和普通方法的覆盖问题。
 */
class Super {	
	public int i=1;
	public Super(){
		System.out.println("父类的构造方法 调用dynamivGet = "+dynamivGet());
		System.out.println("父类的构造方法 调用privateGet = "+privateGet());
	}
	public static String staticGet(){
		return "Base staticGet()";
	}
	public String dynamivGet(){
		return "Base dynamicGet()";
	}
	private String privateGet(){
		return "Base privateGet()";
	}
}

class Sub extends Super{
	public int i=2;

	public Sub(){
		System.out.println("子类的构造方法 调用dynamivGet = "+dynamivGet());
		System.out.println("子类的构造方法 调用privateGet = "+privateGet());
	}
	
	public static String staticGet(){
		return "Derived staticGet()";
	}
	public String dynamivGet(){
		return "Derived dynamicGet()";
	}
	private String privateGet(){
		return "Sub privateGet()";
	}
}
public class Polymorphism{
	public static void main(String[] args){
		Super sup = new Sub();//将子类对方赋给父类引用,定义为父类的类型
		System.out.println("sup.i = "+sup.i); //变量与定义时的类型有关
		System.out.println(sup.staticGet());//静态方法与定义时的类型有关
		System.out.println(sup.dynamivGet());//普通方法与创建对象时的类型有关
		
		Sub sub = new Sub();//定义为子类的类型
		System.out.println("sub.i = "+sub.i);
		System.out.println(sub.staticGet());
		System.out.println(sub.dynamivGet());
	}
}
运行结果输出如下:

 2.多态的实现机制

多态的实现机制基于方法的重载和覆盖,如果父类中没有dynamivGet()方法,则sup.dynamivGet()调用这个方法将会出错。因为子类中没有对父类中的这个方法进行重载或覆盖。当子类中的方法与父类中的方法有相同的签名(相同的方法名,相同的参数个数与类型)时,子类将会覆盖父类的方法,而不会继承。    

        Java中提供了编译时多态和运行时多态。编译时多态是通过方法的重载实现的,运行时多态是通过方法的覆盖(子类覆盖父类的方法)实现的。

3. 重载(overload)和覆盖(override)

        重载(overload)和覆盖(override),其中重载是在同一个类中多态性的表现,是指在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型(特别注意的是子类继承父类的public方法之后,该public方法作为子类中的方法之一,子类中再有其他与该public方法同名但参数不同的方法即可算作重载)。覆盖是指派生类方法覆盖基类方法,覆盖一个方法对其重写,以达到不同的作用。

3.1 使用重载时需要额外注意四点

1)重载是通过不同的方法参数来区分的。说白了就是方法签名中方法名字相同,参数列表不同。(方法名和参数列表合称方法签名,唯一地标识出某个方法);

2)不能通过方法的访问权限、返回值类型和抛出的异常类型来进行重载;

3)对于继承来说,如果基类方法的访问权限是private的,那么就不能在派生类中对其重载,如果派生类中也定义了一个同名的方法,这在子类中是一个新的方法,不会达到重载的效果;如果基类方法的访问权限是public的,在派生类中如果出现了方法名同但是参数不同的则算是重载;

4)参数顺序的不同也可以区分两个方法,算作重载,但是一般不那么做。

3.2 在使用覆盖时需要注意三点

1)派生类中的覆盖方法必须和基类中被覆盖的方法有相同的返回值、方法名和参数列表。

2)派生类中的覆盖方法必须和基类中被覆盖的方法所抛出的异常一致。

3)基类中被覆盖的方法不能为private,否则其子类只是定义了一个新的方法,并没有对覆盖基类中的方法。

3.3   重载与覆盖的区别主要有以下几个方面:

1)覆盖是子类与父类之间的关系,是垂直关系;而重载是同一个类中的多个方法之间的关系;

2)覆盖是子类和父类中相同返回值、方法名和参数列表的方法之间的对应关系;而重载是具有相同方法名的多个方法之间的关系;

3)覆盖要求参数列表相同;而覆盖要求参数列表不同;

4)   覆盖关系中,调用方法体是根据对象的类型(对象对应存储空间类型)来决定,而重载关系是根据调用时的实参数列表与形参列表来选择方法体的。


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值