多态
多态:可以理解为事物存在的多种体现形态。
当几个事物有共同方法时,我们可以将这个共同方法的定义提取出来,封装在一个新的抽象类中,并让这些类继承这个抽象类,子类覆写父类中的方法。此后,我们只需要将父类的引用指向子类,就可以通过子类对象调用父类的方法,实现子类的功能,提高了代码的复用性。
举例:客车,货车 都能运输,将运输工具功能定义提取出来,客车和货车分别在自己子类对运输内容具体化。我们就可以在调用运输工具中,根据对象,调用相应的功能呢。
猫 x = new 猫();
动物 x = new 猫();//一个对象,两种形态。
猫这类事物即具备者猫的形态,又具备着动物的形态。
这就是对象的多态性。
1多态的体现
父类的引用指向了自己的子类对象。
父类的引用也可以接受自己的子类对象。
2多态的前提
必须是类与类之间有关心,要么继承,要么实现。
前提是, 父类的方法被子类方法覆盖。
3多态的好处
多态的出现大大提高了程序的扩展性。
4多态的弊端
提高了扩展性,但是只能使用父类的引用访问父类中的成员。
5多态的应用
6多态的出现代码中的特点(多态使用的注意事项)
abstract class Student
{
public abstract void study();
public void sleep()
{
System.out.println("躺着睡");
}
}
class DoStudent
{
public void doSome(Student stu)
{
stu.study();
stu.sleep();
}
}
class BaseStudent extends Student
{
public void study()
{
System.out.println("base study");
}
public void sleep()
{
System.out.println("蹲着睡");
}
}
class AdvStudent extends Student
{
public void study()
{
System.out.println("Adv study");
}
}
class Test
{
public static void main(String[] args)
{
DoStudent ds = new DoStudent();
ds.doSome(new BaseStudent());
ds.doSome(new AdvStudent());
}
}
类型转换
当我们需要使用子类特有对象时,只需要将父类引用的对象,向下转型为子类对象。就可以调用子类的特有方法。
Animal a= new Cat; //类型提升,向上转型
a.eat();
//如果想要调用猫的特有方法时,如何操作?
//强制将父类的引用,转成子类的类型。向下转型。
Cat c=(Cat)a; //向下转型。
c.catchMouse();
//千万不要出现 将父类对象转成子类类型。
/*我们能转换的是父类应用指向了自己的子类对象时, Animal a= new Cat;
该对应可以被提升。也可以被转换*/
//多态自始至终都是子类对象在做着变化。
abstract class Animal
{
abstract void eat();
}
class Cat extends Animal
{
public void eat()
{
System.out.println("吃鱼");
}
public void catchMouse()
{
System.out.println("抓老鼠");
}
}
class Dog extends Animal
{
public void eat()
{
System.out.println("骨头");
}
public void kanJia()
{
System.out.println("看家");
}
}
public static void main(String[] args)
{
Animal a= new Cat; //类型提升,向上转型
a.eat();
//如果想要调用猫的特有方法时,如何操作?
//强制将父类的引用,转成子类的类型。向下转型。
Cat c=(Cat)a; //向下转型。
c.catchMouse();
//千万不要出现 将父类对象转成子类类型。
/*我们能转换的是父类应用指向了自己的子类对象时, Animal a= new Cat;
该对应可以被提升。也可以被转换*/
//多态自始至终都是子类对象在做着变化。
function(Cat c);
public static void function(Animal a)//Animal a= new Cat;
{
a.eat();
if (a instanceof Cat) //instanceof:用于判断对象的具体类型。只能用于引用数据类型判断
//通常在向下转型前用于健壮性的判断。
{
Cat c= (Cat)a;
c.catchMouse();
}
else if (a instanceof Dog)
{
Dog c= (Dog)a;
c.kanJia();
}
}
}
}
在多态中成员函数的特点:
在编译时期,参阅引用型变量所属的类中是否有调用的方法。
如果有,编译通过。
如果没有,编译失败。
在运行时期,参阅对象所属的类中是否有调用的方法。
简单总结就是:多态调用时:
成员函数
编译看父类是否有该方法,运行看子类的方法体。
静态成员函数:无论编译和运行,都参考左边。
成员变量:
无论编译和运行,都参考左边(引用型变量所属的类)。
class Fu
{
int num= 1;
void method1()
{
System.out.println("fu method-1");
}
void method2()
{
System.out.println("fu method-2");
}
static void method4()
{
System.out.println("fu method-4");
}
}
class Zi extends Fu
{
int num = 2;
void method1()
{
System.out.println("Zi method-1");
}
void method3()
{
System.out.println("Zi method-3");
}
static void method4()
{
System.out.println("Zi method-4");
}
}
class Test
{
public static void main(String[] args)
{
Fu f= new Zi();
f.method1(); //结果是Zi的method1,覆盖
f.method2(); //结果是Fu的method2.
//num全局变量
System.out.println(f.num); //结果是Fu的num
Zi z= new Zi();
System.out.println(z.num); //结果是Zi的num
//method4() 是静态函数
f.method4(); //结果是Fu的method4
z.method4(); //结果是Zi的method4
/*
在多态中成员函数的特点:
在编译时期,参阅引用型变量所属的类中是否有调用的方法。
如果有,编译通过。
如果没有,编译失败。
在运行时期,参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)。
在多态中,静态成员函数的特点:
无论编译和运行,都参考左边。
*/
}
}
/*需求
电脑运行实力
电脑运行基于主板。
*/
interface PCI
{
public void open();
public void close();
}
class MainBoard
{
public void run()
{
System.out.println("mainborad run");
}
public void usbPCI(PCI p) //PCI p=new NetCard() 接口型引用指向自己的子类对象
{
if (p!=null)
{
p.open();
p.close();
}
}
}
class NetCard implements PCI
{
public void open()
{
System.out.println("netcard open");
}
public void close()
{
System.out.println("netcard close");
}
}
class SoundCard implements PCI
{
public void open()
{
System.out.println("sound open");
}
public void close()
{
System.out.println("sound close");
}
}
class Test
{
public static void main (String[] args)
{
MainBoard mb = new MainBoard();
mb.run();
mb.usbPCI(null);
mb.usbPCI(new NetCard());
mb.usbPCI(new SoundCard());
}
}
interface 的应用
/*需求:数据库的操作
数据是:用户信息
1:连接数据库 JDBC Hibernate
2:操作数据库
c create r read u update d delete
3关闭数据库连接
*/
class UserInfoByJDBC implements UserInfoDao
{
public void add(User user)
{
1JDBC连接数据库;
2使用sql添加语句添加数据;
3关闭连接
}
public void delete(User user)
{
1JDBC连接数据库;
2使用sql添加语句删除数据;
3关闭连接
}
}
class UserInfoByHibernate implements UserInfoDao
{
public void add(User user)
{
1JDBC连接数据库;
2使用sql添加语句添加数据;
3关闭连接
}
public void delete(User user)
{
1JDBC连接数据库;
2使用sql添加语句删除数据;
3关闭连接
}
}
interface UserInfoDao
{
public void add(User user);
public void delete(User user);
}
class Test
{
public static void main (String [] args)
{
UserInfoDao ui= new UserInfoByJDBC();
UserInfoDao ui= new UserInfoByHibernate();
ui.add(user);
ui.delete(user);
}
}