多态

1.多态是面向对象的第三大主要特征

如果说继承是为了解决代码重用的问题,那么多态就是为了解决参数的统一问题,多态要结合继承才使用

观察代码

package polymorphic;
class Per{
public void print() {
System.out.println("1.***");
}
public void fun() {
this.print();
}
}
class Stu extends Per{
public void print() {
System.out.println("2.###");
}
}
public class Polya {
public static void main(String[] args) {
// TODO Auto-generated method stub
Stu stu=new Stu();
stu.fun();
}

}

结果:2.###

所谓的多态性指的是父子对象之间的转换操作,那么多态性一共有两种转换形式
.向上转型:父类 父类对象=子类实例,自动完成转换
.向下转型:子类 子类对象=(子类)父类实例,强制转换

.向上转型

package polymorphic;
class Per{
public void print() {
System.out.println("1.***");
}
public void fun() {
this.print();
}
}
class Stu extends Per{
public void print() {
System.out.println("2.###");
}
}
public class Polya {
public static void main(String[] args) {
// TODO Auto-generated method stub
Per per=new Stu();//向上转型,自动完成
per.print();
}

}

结果:2.###

现在Stu重写了print()方法,同时new的是Stu子类,那么一定要找到被重写过的方法,但是需要的是,如果此时子类有扩充有新的方法,那么向上转型之后的对象是无法调用的

package polymorphic;
class Per{
public void print() {
System.out.println("1.***");
}
public void fun() {
this.print();
}
}
class Stu extends Per{
public void print() {
System.out.println("2.###");
}
public void funa() {
System.out.println("3.$$$");
}
}
public class Polya {
public static void main(String[] args) {
// TODO Auto-generated method stub
Per per=new Stu();
per.print();
per.funa();//找不到符号
}

}

因为Per类可以看见的方法一个print(),没有funa(),那么要想取调用funa()方法,则必须执行向下转型,将父类对象变为子类实例向下转型

package polymorphic;
class Per{
public void print() {
System.out.println("1.***");
}
public void fun() {
this.print();
}
}
class Stu extends Per{
public void print() {
System.out.println("2.###");
}
public void funa() {
System.out.println("3.$$$");
}
}
public class Polya {


public static void main(String[] args) {
// TODO Auto-generated method stub
Per per=new Stu();//向上转型,自动转换
per.print();
Stu stu=(Stu)per;//向下转型,强制转换
stu.funa();
}

}

结果:

2.###

3.$$$

阶段性总结:
.向上转型的主要特征,子类为父类对象实例化,调用的方法一定是子类所重写过的方法;(向上转型找共性。)

.向下转型的主要特征,子类扩充了某些功能,而这些功能父类之中发没有定义,则需要执行向下转型,以调用子类特有的功能。(向下转型找特性)

观察以下代码
public class Polya {
public static void main(String[] args) {
// TODO Auto-generated method stub
Per per=new Per();
Stu stu=(Stu)per;//ClassCastException
stu.print();
stu.funa();
}

}

此时的程序出现了“ClassCastException”异常,表示的是类转换异常,指的是两个没有关系的类对象发生转换是所产生的问题
在本程序之中,发现实例化的是一个Per类对象,但是此时没有和任何子类产生关系,在类的定义上,一个类并不能知道有哪些子类,
但是一个子类可以知道谁是它的父类,所以如果要发生向下转型之前,必须首先建立好父子类之间的关系。(向上转型),之后才可以有向下转型

向下转型操作的前提:首先要发生向上转型

由于向下转型危险,有可能会造成错误,在java之中专门有一个instanceof的关键字,利用此关键字就可以方便判断出某一个对象是某个一个类的实例
语法: instanceof类:返回 boolean型数据
package polymorphic;
class Pers{
public void print() {
System.out.println("1.***");
}
public void fun() {
this.print();
}
}
class Stud extends Pers{
public void print() {
System.out.println("2.###");
}
public void funa() {
System.out.println("3.$$$");
}
}
public class Polyb {
public static void main(String[] args) {
// TODO Auto-generated method stub
Pers per=new Pers();
System.out.println(per instanceof Pers);
System.out.println(per instanceof Stud);
}

}

结果:true

false

package polymorphic;
class Pers{
public void print() {
System.out.println("1.***");
}
public void fun() {
this.print();
}
}
class Stud extends Pers{
public void print() {
System.out.println("2.###");
}
public void funa() {
System.out.println("3.$$$");
}
}
public class Polyb {
public static void main(String[] args) {
// TODO Auto-generated method stub
Pers per=new Stud();
System.out.println(per instanceof Pers);
System.out.println(per instanceof Stud);
if(per instanceof Stud)
{
Stud stu=(Stud)per;//向下转型
stu.funa();//调用子类自己扩充的操作
}
}

}

结果:

true

true

3.$$$

疑问?这样的互相转型有什么意义?
假设A类中有学生。工人。教师,三个子类,但是每个身份的人说的话一定不一样。。

观察代码:1.利用方法重载完成

package polymorphic;
class A{
public void say() {
System.out.println("1.我是一个人");
}
}
class Student extends A{
public void say() {
System.out.println("2.我是学生");
}
}
class Worker extends A{
public void say() {
System.out.println("3.我是一个工人");
}
}
class Teacher extends A{
public void say() {
System.out.println("4.我是一名教师");
}
}
public class Polyc {
public static void main(String[] args) {
// TODO Auto-generated method stub
fun(new Student());
fun(new Worker());
fun(new Teacher());
}
public static void fun(Student stu) {
stu.say();
}
public static void fun(Worker wkr) {
wkr.say();
}
public static void fun(Teacher tec) {
tec.say();
}

}

结果:

2.我是学生

3.我是一个工人

4.我是一名教师

此时,面对当前要求的确可以满足,如果说A类产生了9000个子类,而且有可能增加更多的子类,意味着要fun()方法要重载9000此,而且
重复编写相同的代码9000次,同时每当扩充子类的时候,都必须去修改包含有fun()方法类的定义,最重要的原因还在于参数没有得到有效的统一。
2.利用对象的向上转型操作完成

对象在进行向上转型时可以自动完成父类接收子类对象的功能,同时转型之后所谓调用的方法一定随实例化子类的不同,同一个方法一定执行不同的功能

package polymorphic;
class A{
public void say() {
System.out.println("1.我是一个人");
}
}
class Student extends A{
public void say() {
System.out.println("2.我是学生");
}
}
class Worker extends A{
public void say() {
System.out.println("3.我是一个工人");
}
}
class Teacher extends A{
public void say() {
System.out.println("4.我是一名教师");
}
}
public class Polyc {
public static void main(String[] args) {
// TODO Auto-generated method stub
fun(new Student());
fun(new Worker());
fun(new Teacher());
}
public static void fun(A a) {
a.say();
}

}

结果:

2.我是学生

3.我是一个工人

4.我是一名教师

现在结果与之前完全一样,如果随意去扩充子类的话,fun()方法不需要做任何的修改就可以满足所有的功能
思考题:现在假设有一个数组操作类,这个类操作之中需要接收一个数组(通过构造传递),而后在此下有两个子类,一个子类在取得数据的

时候会将传入的数组进行排序,另外一个子类会将传递进去的数组以反转的形式返回。

package polymorphic;
class A{
public void say() {
System.out.println("1.我是一个人");
}
}
class Student extends A{
public void say() {
System.out.println("2.我是学生");
}
}
class Worker extends A{
public void say() {
System.out.println("3.我是一个工人");
}
}
class Teacher extends A{
public void say() {
System.out.println("4.我是一名教师");
}
}
public class Polyc {


public static void main(String[] args) {
// TODO Auto-generated method stub
fun(new Student());
fun(new Worker());
fun(new Teacher());
}
public static void fun(A a) {
a.say();
}

}
现在结果与之前完全一样,如果随意去扩充子类的话,fun()方法不需要做任何的修改就可以满足所有的功能
思考题:现在假设有一个数组操作类,这个类操作之中需要接收一个数组(通过构造传递),而后在此下有两个子类,一个子类在取得数据的
时候会将传入的数组进行排序,另外一个子类会将传递进去的数组以反转的形式返回。
package polymorphic;
class Array{
private int data[];
public Array(int data[]){
this.data=data;
}
public int[] getData() {
return this.data;
}
}
class SortArray extends Array{
public SortArray(int data[]) {
super(data);
}
//发现父类的getData()方法支持不足,但是又必须使用此方法
public int [] getData() {
java.util.Arrays.sort(super.getData());
return super.getData();
}
}
class ReverseArray extends Array{
public ReverseArray(int data[]) {
super(data);
}
public int [] getData() {
int center=super.getData().length/2;
int head=0;
int tail=super.getData().length-1;
for(int x=0;x<center;x++)
{
int temp=super.getData()[head];
super.getData()[head]=super.getData()[tail];
super.getData()[tail]=temp;
head++;
tail--;
}
return super.getData();
}
}
public class Polyd {
public static void main(String[] args) {
// TODO Auto-generated method stub
Array arr=new Array(new int[] {5,6,7,2,3,4});
print(arr);
}
public static void print(Array temp) {
int result[]=temp.getData();
for(int x=0;x<result.length;x++) {
System.out.print(result[x]+",");
}
System.out.println();
}

}

结果:5,6,7,2,3,4,

总结:关于继承性与多态性
这两种特性一定时相辅相成的,不可以缺一;
继承性解决的是一个类功能扩充的问题,而多态性解决的是参数统一的问题,有了多态性之后才应该发觉,
父类的设计是相当重要的,而且子类不要轻易的扩充父类里面没有的方法
总结:关于对象转型问题:
向上转型(大多数):自动完成,子类对象自动的转换为父类对象,而后调用的是子类所重写过的方法,利用对象的向上转型就可以很好的解决参数统一
向下转型(极少):强制完成,不建议出现,当需要调用子类自己扩充方法的时候
不转型,很多时候的一些类是不会进行转型操作,例如;String类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值