JavaSE学习笔记_5:Java多态

来源:互联网 发布:暴雪防沉迷算法 编辑:程序博客网 时间:2024/05/22 00:47

Java多态

 

一、多态(面向对象的第三个特征)

1、多态—概念

多态:可以理解为事物存在的多种体现形式。

人:男人,女人

动物:猫,狗

猫 x=new 猫();

动物 x=new 动物();//实体x既具备猫的类型也具备动物的类型。

 

多态的前提:必须是类与类之间有关系。要么继承,要么实现。

多态的体现:父类引用指向子类对象。父类引用也可以接收子类对象。

多态的好处:大大的提高程序的扩展性和代码的复用性。

多态的弊端:只能使用父类的引用去访问被子类复写的父类功能。可以转型。(创建对象时是向上转型,如:Animal a=new Cat(),想调用子类中特有的功能向下转型(强转),如:Cat c=(Cat)a)

 

2、多态—扩展性

3、多态—转型

 

用实例来讲解:

/*

动物

猫,狗

*/

一开始:

abstract class Animal

{

public abstract void eat();//吃啥不确定,每个动物 //的事物都不一样。

}

 

//定义子类

class Cat extends Animal

{

//由子类来实现未知的内容

public void eat()

{

System.out.println(“吃鱼”);

}

//子类自己独有的功能

public void catMouse()

{

System.out.println(“抓老鼠”);

}

}

 

class Dog extends Animal

{

public void eat()

{

System.ou.println(“吃骨头”);

}

public void kangjia()

{

System.out.println(“看家”);

}

}

 

class Pig extends Animal

{

public void eat()

{

System.ou.println(“吃饲料”);

}

public void gongdi()

{

System.out.println(“拱地”);

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

Cat c=new Cat();

c.eat();

Cat c2=new Cat();

c2.eat();

 

Dog d=new Dog();

d.eat();

Dog d1=new Dog();

d1.eat();

 

Pig p=new Pig();

p.eat();

Pig p1=new Pig();

p1.eat();

}

}

发现以上主函数中的代码好死板,我们可以:

abstract class Animal

{

public abstract void eat();//吃啥不确定,每个动物 //的事物都不一样。

}

 

//定义子类

class Cat extends Animal

{

//由子类来实现未知的内容

public void eat()

{

System.out.println(“吃鱼”);

}

//子类自己独有的功能

public void catMouse()

{

System.out.println(“抓老鼠”);

}

}

 

class Dog extends Animal

{

public void eat()

{

System.ou.println(“吃骨头”);

}

public void kangjia()

{

System.out.println(“看家”);

}

}

 

class Pig extends Animal

{

public void eat()

{

System.ou.println(“吃饲料”);

}

public void gongdi()

{

System.out.println(“拱地”);

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

function(new Cat());

function(new Cat());

 

function(new Dog());

function(new Dog());

 

function(new Pig());

function(new Pig());

}

pubic static void function(Cat c)

{

c.eat();

}

pubic static void function(Dog d)

{

d.eat();

}

pubic static void function(Pig c)

{

p.eat();

}

}

发现这样的话,如果再来一个动物鸡,那么主类中还需写一个function()以重载形式出现。动物越多,function()重载越多。因此另辟蹊径:

abstract class Animal

{

public abstract void eat();//吃啥不确定,每个动物 //的事物都不一样。

}

 

//定义子类

class Cat extends Animal

{

//由子类来实现未知的内容

public void eat()

{

System.out.println(“吃鱼”);

}

//子类自己独有的功能

public void catMouse()

{

System.out.println(“抓老鼠”);

}

}

 

class Dog extends Animal

{

public void eat()

{

System.ou.println(“吃骨头”);

}

public void kangjia()

{

System.out.println(“看家”);

}

}

 

class Pig extends Animal

{

public void eat()

{

System.ou.println(“吃饲料”);

}

public void gongdi()

{

System.out.println(“拱地”);

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

function(new Cat());

function(new Cat());

 

function(new Dog());

function(new Dog());

 

function(new Pig());

function(new Pig());

}

pubic static void function(Animal a)

{

c.eat();

}

}

但是,这样虽好,却只能调用子类中重写的方法。因此可以向下转型:

abstract class Animal

{

public abstract void eat();//吃啥不确定,每个动物 //的事物都不一样。

}

 

//定义子类

class Cat extends Animal

{

//由子类来实现未知的内容

public void eat()

{

System.out.println(“吃鱼”);

}

//子类自己独有的功能

public void catMouse()

{

System.out.println(“抓老鼠”);

}

}

 

class Dog extends Animal

{

public void eat()

{

System.ou.println(“吃骨头”);

}

public void kangjia()

{

System.out.println(“看家”);

}

}

 

class Pig extends Animal

{

public void eat()

{

System.ou.println(“吃饲料”);

}

public void gongdi()

{

System.out.println(“拱地”);

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

function(new Cat());

function(new Cat());

 

function(new Dog());

function(new Dog());

 

function(new Pig());

function(new Pig());

}

pubic static void function(Animal a)

{

a.eat();

Cat c=(cat)a;

c.catchMouse();//调用了子类自己特有的内容。

}

}

但是,如果传入的是new Dog(),则编译通过,运行失败,发生类型转化异常:ClassCastException。则:

abstract class Animal

{

public abstract void eat();//吃啥不确定,每个动物 //的事物都不一样。

}

 

//定义子类

class Cat extends Animal

{

//由子类来实现未知的内容

public void eat()

{

System.out.println(“吃鱼”);

}

//子类自己独有的功能

public void catMouse()

{

System.out.println(“抓老鼠”);

}

}

 

class Dog extends Animal

{

public void eat()

{

System.ou.println(“吃骨头”);

}

public void kangjia()

{

System.out.println(“看家”);

}

}

 

class Pig extends Animal

{

public void eat()

{

System.ou.println(“吃饲料”);

}

public void gongdi()

{

System.out.println(“拱地”);

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

function(new Cat());

function(new Cat());

 

function(new Dog());

function(new Dog());

 

function(new Pig());

function(new Pig());

}

pubic static void function(Animal a)

{

b.eat();

if(a instanceof Cat)

{

Cat c=(Cat)a;

a.catchMouse();

}

else if(a instanceof Dog)

{

Dog d=(Dog)a;

d.kangjia();

}

else if(a instanceof Pig)

{

Pig p=(Pig)a;

p.gongDi();

}

}

}

上述代码,如果动物越多,判断也就越多,也不是好办法。待留。还有就是不建议在function()中首先对Animal类型做判断,因为无论如何也都成立。

 

还有就是,将function()单独放在一个类中,这个类与Animal类共同成为一个体系。

4、多态中成员的特点

Fu f=new Zi();(Fu可以是一个类,也可以是一个接口)

(1)在多态中成员函数的特点

1)在编译时期,参阅引用型变量所属的类是否有调用的方法。如果有,编译通过;如果没有,编译失败。

2)在运行时期,参阅对象所属的类中是否有调用的方法。如果有,运行通过;如果没有,运行失败。

简单总结:编译看左边,运行看右边。

(2)在多态中成员变量的特点

无论编译和运行,都参考左边(引用型变量所属的类)

(3)在多态中静态成员变量的特点

无论编译和运行,都参考左边(引用型变量所属的类)

(4)在多态中静态成员函数的特点

无论编译和运行,都参考左边(引用型变量所属的类)

 

示例1:

/*电脑主板*/

//功能单一的主板逐渐增添多个功能。

 

一开始

class MainBoard

{

public void run()

{

System.out.println(“mainboard run”);

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

MainBoard mb=new MainBoard();

mb.run();

}

}

主板功能太单一。现在想上网,买来网卡

class MainBoard

{

public void run()

{

System.out.println(“mainboard run”);

}

public void useNetCard(netCard c)

{

c.open();

c.close();

}

}

//定义网卡

class NetCard

{

public void open()

{

System.out.println(“netcard open”);

}

public void close()

{

System.out.println(“netcard close”);

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

MainBoard mb=new MainBoard();

mb.run();

mb.useNetcard(new NetCard());

}

}

现在又想听音乐,又买来一个声卡,则还得修改主板,耦合性强。发现主板毫无扩展性可言。现在利用多态的思想:

interface PCI

{

Public abstract void open();

Public abstract void close();

}

class MainBoard

{

public void run()

{

System.out.println(“mainboard run”);

}

public void usePCI(PCI   p)

{

  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(“Soundcard open”);

}

public void close()

{

System.out.println(“Soundcard close”);

}

}

 

class DuoTaiDemo

{

public static void main(String[] args)

{

MainBoard mb=new MainBoard();

mb.run();

mb.usePCI(new NetCard());

mb.usePCI(new SoundCard());

}

}

 

实例2:

/*

数据库的操作:

1、连接数据库。JDBC、Hibernate两种方式

2、操作数据库。c:creat r:read u:update d:delete

3、关闭数据库。

*/

 

一开始:我们用jdbc的方式连接数据库:

class UserInfoByJDBC

{

public void add(User user)

{

1、JDBC连接数据库。

2、使用sql添加语句添加数据。

3、关闭数据库。

}

public void delete(User user)

{

1.JDBC连接数据库。

2.使用sql删除语句删除数据。

3.关闭数据库。

}

}

class DBOperate

{

public static void main(String[] args)

{

UserInfoByJDBC ui=new UserInfoByJDBC();

ui.add(user);

ui.add(user);

}

}

后来,我们又想通过Hibernate方式连接。则:

class UserInfoHibernate

{

public void add(User user)

{

4、Hibernate连接数据库。

5、使用sql添加语句添加数据。

6、关闭数据库。

}

public void delete(User user)

{

4.Hibernate连接数据库。

5.使用sql删除语句删除数据。

6.关闭数据库。

}

}

class DBOperate

{

public static void main(String[] args)

{

UserInfoByHibernate ui=new 

            UserInfoByHibernate();

ui.add(user);

ui.add(user);

}

}

发现连接方式和主程序的耦合性非常强。因此利用多态的思想:

interface UserInfoDao

{

public void add();

public void delete();

}

class UserInfoByJDBC implements UserInfoDao

{

public void add(User user)

{

7、JDBC连接数据库。

8、使用sql添加语句添加数据。

9、关闭数据库。

}

public void delete(User user)

{

7.JDBC连接数据库。

8.使用sql删除语句删除数据。

9.关闭数据库。

}

}

Class UserInfoByHibernate implements UserInfoDao

{

public void add(User user)

{

10、Hibernate连接数据库。

11、使用sql添加语句添加数据。

12、关闭数据库。

}

public void delete(User user)

{

10.Hibernate连接数据库。

11.使用sql删除语句删除数据。

12.关闭数据库。

}

}

class DBOperate

{

Public static void main(String[] args)

{

UserInfoDao ui=new UserInfoByJDBC()/

UserInfoByHibernate();

ui.add(user);

ui.delete(user);

}

}

这样,主程序只和interface有关系,与UserInfoByJDBC/UserInfoByHibernate无关。当主程序中还有一个地方需要改,想让它也不用改,则涉及到以后的反射。

 


2015-11-202015-11-20

0 0
原创粉丝点击