java对象的多态性

1 篇文章 0 订阅

1. 定义

如果B类是A类的子类或间接子类,当用B类创建对象b并将这个对象b的引用赋给A类对象a时,如:
A a;
a = new B();
OR
A a;
B b = new B();
a = b;
则称A类对象a是子类B对象b的上转型对象。


2. 性质

对象b的上转型a的实体是有子类B创建的,但是上转型对象会失去子类B的一些属性和功能。上转型对象具有以下特点:
1.上转型对象不能操作子类新增加的成员变量,不能使用子类新增的方法。即为较子类B失去一些属性和功能,这些属性和功能是新增的。
2.上转型对象可以操作子类继承或隐藏的成员变量,也可以使用子类继承的或重写的方法。即为上转型对象可以操纵父类原有的属性和功能,无论这些方法是否被重写。
3.上转型对象调用方法时,就是调用子类继承和重写过的方法。而不会是新增的方法,也不是父类原有的方法。
可以将对象的上转型对象再强制转换到一个子类对象,强制转换过的对象具有子类所有属性和功能。


3. 举例

如:
OutputStream output;
output = new FileOutputStream(filename);


并且根据Java API知
java.lang.Object
  java.io.OutputStream

     java.io.FileOutputStream

这时,output就是上转型对象啦。有什么特殊呢?就是output可以使用FileOutputStream从父类OutputStream那里继承来的方法和重写的方法,而不能使用子类FileOutputStream自己新增的方法啦。最后,这种方法是很常用的哦。。。当父类有很多子类时,就能实现方法的多态。

多态中非静态成员方法的特点

  • 在编译时,参阅引用型变量所属的类中是否有调用的方法。如果有,则编译通过,如果没有没有则编译失败。
  • 在运行时,参阅对象所属的类中是否有调用的方法。
简单总结:成员方法在多态调用的时候编译时看左边,运行时看右边。

多态中静态成员方法的特点

编译和运行都看左边。

多态中成员变量的特点

无论编译或者运行的时候都看左边(引用型变量所属的类)。
/**
 * 多态中成员方法和成员变量的特点
 * 非静态成员方法:编译时看左边(父类),运行时看右边(子类)
 * 静态成员方法:编译和运行都参考左边(父类)
 * 成员变量:编译和运行都看左边(父类)
 */

class Fu{
	
	static int count = 100;	// 父类中的静态成员变量
	int num = 100;			// 父类中的非静态成员变量
	
	public void fun1(){
		System.out.println("父类中的fun1方法");
	}
	public void fun2(){
		System.out.println("父类中的fun2方法");
	}
	public static void fun4(){
		System.out.println("父类中的fun4静态方法");
	}
}

class Zi extends Fu{
	
	static int count = 0; 	// 子类中的静态成员变量
	int num = 0; 			// 子类中的非静态成员变量
	
	@Override
	public void fun1() {
		System.out.println("子类中的fun1方法,覆写了父类的fun1方法");
	}
	
	public void fun3(){
		System.out.println("子类中的fun3方法,此方法是子类特有的");
	}
	
	public static void fun4(){
		System.out.println("子类中的fun4静态方法");
	}
}

public class PolymorphismDemo {

	public static void main(String[] args) {
		
		Fu obj = new Zi();
		obj.fun1();	// 调用子类重写的方法,输出“子类中的fun1方法,覆写了父类的fun1方法”
		obj.fun2();	// 子类中没有重写fun2,则调用父类的fun2方法,打印“父类中的fun2方法”
//		obj.fun3();	//编译失败,因为父类中没有fun3方法,fun3方法是子类特有的
		obj.fun4();	// fun4是父类和子类都有的静态方法,打印“父类中的fun4静态方法”(因为Fu obj加载的是父类,静态不需要创建对象直接调用方法)
		
		System.out.println("obj.num = " + obj.num);		// 非静态成员变量编译和运行都看左边即num = 100
		System.out.println("obj.count = " + obj.count);	// 静态成员变量在类加载的是否确定值,看左边即count = 100
	}
}


对象的多态性

在对象实例化的时候A a = new B(),中满足B is-a A的关系(因为B extends A),而A a = new A(),中同样满足A is-a A的关系。

多态数组

abstract class Animal {
	public abstract void eat();

	public void sleep() {
		System.out.println("动物睡觉!");
	}
}

class Dog extends Animal {

	@Override
	public void eat() {
		System.out.println("我是狗,我吃肉!");
	}

}

class Cat extends Animal {

	@Override
	public void eat() {
		System.out.println("我是猫,我吃鱼");
	}

}

class Bird extends Animal {

	@Override
	public void eat() {
		System.out.println("我是鸟,我吃虫子。");
	}

}

public class Test {
	public static void main(String[] args) {
		/* 创建对象数组 */
		Animal[] animals = { new Dog(), new Cat(), new Bird() };
		for (Animal animal : animals) {
			animal.eat();
			animal.sleep();
		}
	}
}
运行结果:
我是狗,我吃肉!
动物睡觉!
我是猫,我吃鱼
动物睡觉!
我是鸟,我吃虫子。
动物睡觉!

对象的多态性中调用的是被子类覆写的方法。

方法参数的多态性

public class Test {
	public static void main(String[] args) {
		/* 创建对象数组 */
		Animal[] animals = { new Dog(), new Cat(), new Bird() };
		for (Animal animal : animals) {
			fun(animal);
		}
	}
	
	/*方法参数的多态*/
	public static void fun(Animal animal){
		animal.eat();
	}
}

运行结果:
我是狗,我吃肉!
我是猫,我吃鱼
我是鸟,我吃虫子。
执行各自的eat()方法。

如果程序编写的时候使用多态参数——也就是说将参数声明为父类类型,就可以在运行的时候传入子类对象。在以上的例子中如果别人写了一个Rabbit类,那么它就可以直接使用fun()方法,而不需要任何的修改。


Q1:你能够继承任何一个类么?

A1:继承中的一些限制:①存取控制(非public类)只能在同一个包中有子类;②final关键字修饰的类不能被继承;③构造方法私有化,没有子类。

方法覆写时应该遵循的规则:
①:方法的返回值和参数必须完全一样;
②:不能降低方法的访问权限。

方法的重载与多态毫无关系。(重载只是参数 不同)

一个抽象类除了被继承外没有任何其他作用。

为什么要有抽象方法?
将有方法体的方法放在父类中是一个好主意。但是有的时候就是没有办法给出对于任何子类都有意义的程序代码。抽象方法的意义就在于就算无法实现出方法的内容,但是也可以定义出一组子型共同的协议。这样做的好处就是多态。各个子类可以根据自己的需要去覆写父类中的抽象方法。
在继承树结构中的第一个具体类必须实现抽象类中的所有抽象方法。

Object类
public class Object,Object类是所有类的父类,是一个具体的类,常用的方法有:equals()、hashCode()方法、toString()方法和getClass()方法,强烈建议用自己的方法去覆盖原来的equals()、hashCode()方法和toString()方法。

Object类的两个目的:
1.作为多态让方法可以应付多种类型的机制。
2.提供java在执行期间对任何对象都有需要的方法的实现程序代码(让所有的类都会继承到)。有一部分的方法和线程有关。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值