面向对象的第三个特征:多态
定义:某一类事物的多种存在形态
例:动物中猫、狗
猫这个对象对应的类型是猫类型:猫 x=new 猫();
同时猫也是动物中的一种,也可以把猫称为动物:动物 y=new 猫();
动物是猫和狗具体事物中抽取出来的父类型。
父类型引用指向了子类对象。
多态:可以理解为事物存在的多种体现形态
人:男人,女人
动物:猫、狗
猫 x=new 猫();
动物 x=new 猫();
1、多态的体现
父类的引用指向了自己的子类对象
父类的引用也可以接收自己的子类对象
2、多态的前提
必须是类与类之间有关系,要么继承,要么实现
通常还有一个前提:存在覆盖
3、多态的好处
多态的出现大大的提高了程序的扩展性。
4、多态的弊端:
提高了扩展性,但是只能使用父类的引用访问父类中的成员。
5、多态的应用
6、多态的出现代码中的特点(多态使用的注意事项)
class DuoTaiDemo
{
Animal a=new Cat();//类型提升,向上转型
a.eat();
}
如果想要调用猫的特有方法时如何操作?
Cat c=new Cat();
c.catchMouse();
这样写是错的,因为Cat c=new Cat();这句话是另一只猫去干抓老鼠的事儿了
应该强调将父类的引用转成子类类型。向下转型
Cat c=(Cat)a;
c.catchMouse();
但如果写成以下形式又是错误的了,因为不能强制将一个动物转成猫。
千万不要出现这样的操作,将父类对象转成子类类型。
我们能转换的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。
多态自始至终都是子类对象在做着变化
Animal c=new Animal();
Cat c=(Cat)a;
在多态中,成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过;如果没有,编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
class Fu13
{
void method_1()
{
System.out.println("Fu method_1");
}
void method_2()
{
System.out.println("Fu method_2");
}
}
class Zi13 extends Fu13
{
void method_1()
{
System.out.println("Zi method_1");
}
void method_3()
{
System.out.println("Zi method_3");
}
}
class ExtendsDemo15
{
public static void main(String[] args)
{
Fu13 f=new Zi13();
f.method_1();//这句运行结果是"Zi method_1",因为虽然子化妆成了父但调用的仍是子的方法
f.method_2();
//f.method_3();如果加上这句就会编译失败,因为父类中没有“method_3()”方法
}
}
在多态中,成员变量的特点:
无论编译和运行都参考左边(引用型变量所属的类)
class Fu14
{
int num=5;
void method_1()
{
System.out.println("Fu method_1");
}
void method_2()
{
System.out.println("Fu method_2");
}
}
class Zi14 extends Fu14
{
int num=8;
void method_1()
{
System.out.println("Zi method_1");
}
void method_3()
{
System.out.println("Zi method_3");
}
}
class ExtendsDemo18
{
public static void main(String[] args)
{
Fu14 f=new Zi14();
System.out.println(f.num);//这个打印的结果是:5
Zi14 z=new Zi14();
System.out.println(z.num);//这个打印的结果是:8
}
}
在多态中,静态成员函数的特点:
无论编译和运行都参考左边
class Fu18
{
int num=5;
void method_1()
{
System.out.println("Fu method_1");
}
void method_2()
{
System.out.println("Fu method_2");
}
static void method_4()
{
System.out.println("Fu method_4");
}
}
class Zi18 extends Fu18
{
int num=8;
void method_1()
{
System.out.println("Zi method_1");
}
void method_3()
{
System.out.println("Zi method_3");
}
static void method_4()
{
System.out.println("Zi method_4");
}
}
class ExtendsDemo19
{
public static void main(String[] args)
{
Fu18 f=new Zi18();
f.method_4();//运行结果是:"Fu method_4"
}
}
需求:数据库的操作
数据是:用户信息
1、连接数据库 JDBC Hibernate
2、操作数据库
增删改查
c create r read u update d delete
3、关闭数据库连接
class UserInfoByIDBC
{
public void add(User user)
{
1、连接数据库
2、使用sql添加语句添加数据
3、关闭连接
}
public void delete(User user)
{
1、连接数据库
2、使用sql添加语句删除数据
3、关闭连接
}
}
Object类中已经提供了对对象是否相同的比较方法
如果自定义类中也有比较相同的功能,没有必要重新定义,只要沿袭父类中的功能,建立自己特有的比较内容即可。这就是覆盖。class Demo14
{
private int num;
Demo14(int num)
{
this.num=num;
}
public boolean equals(Object obj)//Object obj=new Demo();父类引用指向了子类对象,所以要将父类向下转型再比较.
//equals是Object类中的方法,这里是将Object类中的equals方法复写
{
Demo14 d=(Demo14)obj;
return this.num==d.num;
}
}
class ObjectDemo3
{
public static void main(String[] args)
{
Demo14 d1=new Demo14(4);
Demo14 d2=new Demo14(4);
System.out.println(d1.equals(d2));
}
}