面向对象(多态+接口实现)-第18天

来源:互联网 发布:蛐蛐钢琴软件 编辑:程序博客网 时间:2024/05/17 23:13

面向对象(多态+接口实现)

98_面向对象(多态-概念)

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

重载覆盖就是函数多态体现。

人:男人,女人。这就是人的多态。

 

动物:猫,狗

猫 x=new 猫();

动物 x=new 猫();

 

1,多态的基本体现

父类引用指向了自己的子类对象。

2,多态的前提

必需是类与类之间有关系。要么继承,要么实现。

通常还有一个前提,存在覆盖。

3,多态的好处

多态的出现大大的提高程序的扩展性。

多态的弊端:

提高了扩展性,但是只能使用父类的引用,访问父类中的成员。   

4,多态的应用。

 

 

99_面向对象(多态-扩展性)

1,多态的基本体现

父类的引用指向了自己的子类对象。

父类的引用也可以接受自己的

动物:猫,狗。

class Animal

{

void eat()

{

}错误,eat吃什么,不确定。

}

改成抽象:

abstract class Animal

{

public abstractvoid eat();吃是一种多态。

}

class Cat extendsAnimal

{

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(看家);

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

Cat c=new Cat();

c.eat();打印吃鱼。

Dog d=new Dog();

d.eat();打印吃骨头。

Cat c1=new Cat();

c1.eat();打印吃鱼。

Cat c2=new Cat();

c2.eat();打印吃鱼。

}

封装方法.eat()。

class DuoTaiDemo

{

public static void main(String[] args)

{

Cat c=new Cat();

Cat c1=new Cat();

function(c1);打印吃鱼。

function(new Dog());打印吃骨头

}

public static void function(Cat c)

{

c.eat();

}

public static void function(Dog d)

{

d.eat();

}

 

一年后,还有养猪。

class Animal

{

void eat()

{

}错误,eat吃什么,不确定。

}

改成抽象:

abstract class Animal

{

public 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(看家);

}

}

养猪

class Pig extends Animal

{

public void eat()

{

system.out.println(饲料);

}

public void gongDi()

{

system.out.println(拱地);

}

}

public static void function(Cat c)

{

c.eat();

}

public static void function(Dog d)

{

d.eat();

添加了猪的吃

public static void function(Pigp)

{

p.eat();

}

class DuoTaiDemo

{

public static void main(String[] args)

{

Cat c=new Cat();

Cat c1=new Cat();

function(c1);打印吃鱼。

function(new Dog());打印吃骨头

function(new Pig());打印饲料

}

 

对比:

abstract class Animal

{

public 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(看家);

}

}

class Pig extends Animal

{

public void eat()

{

system.out.println(饲料);

}

public void gongDi()

{

system.out.println(拱地);

}

}

public static void function(Cat c)

{

c.eat();

}

public static void function(Dog d)

{

d.eat();

添加了猪的吃。

public static void function(Pig p)

{

p.eat();

}

class DuoTaiDemo

{

public static void main(String[] args)

{

Animal c=newCat();为什么可以这样呢???一个对象具备多种形态造成的。c是猫,也是动物。把动物变成了具体的猫。

c.eat(); 打印吃鱼。子类覆盖父类eat()

}

 

对比:

abstract class Animal

{

public 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(看家);

}

}

class Pig extends Animal

{

public void eat()

{

system.out.println(饲料);

}

public void gongDi()

{

system.out.println(拱地);

}

}

public static void function(Animal a)这时,变成了Animal a=new Cat()

{

a.eat();

}

class DuoTaiDemo

{

public static void main(String[] args)

{

function(new Cat());注意:不是function(new Cat);

function(new Dog());打印:吃骨头。

function(new Pig());

}

3,多态的好处

多态的出现大大的提高程序的扩展性

 

 

100_面向对象(多态-转型)

abstract class Animal

{

public abstract void eat();吃是一种多态。

}

class Cat extendsAnimal

{

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(看家);

}

}

class Pig extends Animal

{

public void eat()

{

system.out.println(饲料);

}

public void gongDi()

{

system.out.println(拱地);

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

Animal a=new Cat();类型提升。 byte b=1;int x=b;把猫提升为动物。向上转型。转成父类型。动物具备了猫的属性。

a.eat();找的是父类的内容运行起来的是子类内容

如果想要调用猫的特有方法时,如何操作?

强制将父类的引用。转成子强制类的类型。向下转型。

Cat c=(Cat)a;//强制把动物转换成猫

c .catchMouse();

我们转换的是父类应用指向了自己的子类对象时,该应用可以被提升,也可以被转换。

多态自始自终都是子类对象在做着变化

对比:千万不用出现这样的操作,就是将父类对象转成子类类型。下面是错误的。

Animal a=new Animal();

Cat c=(Cat)a;

}

}

打印:

吃鱼

抓老鼠

 

人物举例:

毕姥爷 x=new 毕老师();毕老师变成了毕姥爷。

x.讲课();虽然变成了毕姥爷,但是运行的是毕老师讲课的内容,讲java内容。

毕老师 y=(毕老师)x;再把毕姥爷变回成毕老师。

y.看电影();然后毕老师可以陪朋友去看电影了。哈哈。。。

 

abstract class Animal

{

public abstractvoid 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(看家);

}

}

class Pig extends Animal

{

public void eat()

{

system.out.println(饲料);

}

public void gongDi()

{

system.out.println(拱地);

}

}

public static void function(Animal a)

{

a.eat();

Cat c=(Cat)a;

c.catMouse();

}

class DuoTaiDemo

{

public static void main(String[] args)

{

function(new Cat());

}

}

打印:

吃鱼

抓老鼠

 

当调用Dog会出现什么情况呢?

abstract class Animal

{

public 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 function(Animal a)

{

a.eat();

Cat c=(Cat)a;

c.catMouse();

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

function(new Dog());//错误。这时,调用的Dog。而Dog不能转换成Cat

}

}

 

运用instanceof实例化来判断就可以知道。是不是属于该类。

abstract class Animal

{

public 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 function(Animal a)

{

a.eat();

if(a instanceof Cat)//a的实例化是Cat吗?a属于Cat吗?

{

Cat c=(Cat)a;

c.catMouse();

}

else if(a instanceof Dog)//a的实例化是Dog吗?

{

Cat c=(Cat)a;

c.catMouse();

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

function(new Dog());

}

}

打印:

吃骨头

看家

 

当a先是实例化Animal,然后a实例化Cat

abstract class Animal

{

public abstractvoid 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 function(Animal a)

{

a.eat();

if(a instanceofAnimal)//a的实例化是Cat吗?a属于Animal吗?

{

System.out.println(haha);

}

else if(a instanceof Cat)//a的实例化是Cat吗?

{

Cat c=(Cat)a;

c.catMouse();

}

else if(a instanceof Dog)//a的实例化是Dog吗?

{

Cat c=(Cat)a;

c.catMouse();

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

function(new Cat());

function(new Dog());

}

}

打印:

吃骨头

haha

看家

haha

 

 

102_面向对象(多态中成员的特点)

class Fu

{

void method1()

{

System.out.println(fu method_1);

}

void method2()

{

System.out.println(fu method_2);

}

}

class Zi extends Fu

{

void method1()

{

System.out.println(zi method_1);//Zi_1把父类的Zi_1覆盖了。

}

void method3()

{

System.out.println(zi method_3);

}

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

Zi z=new Zi();

z.mothod1();//zi method_1

z.mothod2();//fu method_2

z.mothod3();//zi method_3

}

}

重点!!!

多态中,成员函数的特点

在编译时期:查阅引用型变量所属的类是否有调用方法。如果有,编译通过。

在运行时期:参阅对象所属的类中是否有调用的方法。

简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。

对比:

class DuoTaiDemo

{

public static void main(String[] args)

{

Fu f=new Zi();//父类引用子类

f.mothod1();//zi method_1。编译通过,父类有该方法;运行看右边,结果是子类的

f.mothod2();//fu method_2

}

}

 

对比:

class DuoTaiDemo

{

public static void main(String[] args)

{

Fu f=new Zi();

f.mothod1();

f.mothod2();

f.mothod3();//编译失败。编译的时候对象Zi还没产生,系统会Fu中,发现没有mothod3.

}

}

图1

 

面试用:

多态中,成员变量的特点:

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

class Fu

{

int num=5;//成员变量num=5

void method1()

{

System.out.println(fu method_1);

}

void method2()

{

System.out.println(fu method_2);

}

}

class Zi extends Fu

{

int num=8;

void method1()

{

System.out.println(zi method_1);

}

void method3()

{

System.out.println(zi method_3);

}

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

Fu f=new Zi();

System.out.println(f.num);//打印是父类的num=5,成员变量没有覆盖操作

Zi z=new Zi();

System.out.println(z.num);

}

}

打印:

5

8

 

面试用:

多态中,静态成员函数的特点:

无论编译和运行,都参考左边。静态随着类加载

class Fu

{

static int num=5;

static void method1()

{

System.out.println(fu method_1);

}

void method2()

{

System.out.println(fu method_2);

}

}

class Zi extends Fu

{

int num=8;

static void method1()

{

System.out.println(zi method_1);

}

void method3()

{

System.out.println(zi method_3);

}

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

Fu f=new Zi();

System.out.println(f.num);//5。num对象也是静态的。

Fu f=new Zi();

f.mothod1();//fu method_1。mothod的是静态,f.mothod1()相当于类.静态方法,就是类名调用。

Zi z=new Zi();

z.mothod1();//zi method_1

}

}

 

 

103_面向对象(多态的主板示例)

需求:

电脑运行实例,

电脑运行基于主板。

class MainBoard

{

public void run()

{

System.out.println(mainboard);

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());

}

}

打印:

mainboard

netcard open

netcard close

 

主板要实现多功能

interface PCI

{

public void open();//这个相当于抽象的父类方法

public vodi close();

}

class MainBoard

{

public void run()

{

System.out.println(mainboard run);

}

public void usePCI(PCI p)

{

p.open();此时p=null,空指针,调用方法错误。

p.close();

}

}

class DuoTaiDemo

{

public static void main(String[] args)

{

MainBoard mb=new MainBoard();

mb.run();

mb.usePCI(null);//运行出现空值异常。nullpointerexception

}

}

 

interface PCI

{

public void open();

public vodi close();//父类抽象的方法

}

class MainBoard

{

public void run()

{

System.out.println(mainboard run);

}

public void usePCI(PCI p)//PCI p=new NetCard()。接口型引用指向自己的子类对象。

{

if(p!=null)//检测插槽是否为空。

{

p.open();

p.close();

}

}

}

class NetCard implements PCI//implements实现端口      

{

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.usePCI(null);//这句自动跳过

mb.usePCI(new NetCard());//mb.usePCI.NetCard(),为什么不可以这样?NetCard没有被public修饰

}

}

打印:

mainboard run

netcard open

netcard close

 

 

104_面向对象(多态的扩展示例)

需求:数据库的操作。

数据是:用户信息。

1,连接数据库JDBC Hinernate

2,操作数据库。

c create r read u update d delete

3,关闭数据库连接。

 

class UserInfoByJDBC

{

pulic void add(User user)

{

1,JDBC连接数据库。;

2,使用sql添加语句添加数据。;

3,关闭连接。

}

pulic 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.delete(user);

}

}

 

通过Hibernate连接。

class UserInfoByHibernate

{

pulic void add(User user)

{

1,Hibernate连接数据库。;

2,使用sql添加语句添加数据。;

3,关闭连接。

}

pulic void delete(User user)

{

1,Hibernate接数据库。;

2,使用sql添加语句删除数据。;

3,关闭连接。

}

}

class DBOperate

{

public static void main(String[] args)

{

UserInfoByHibernate ui =newUserInfoByHibernate();

ui.add(user);

ui.delete(user);

}

}

 

两次变化,主函数都需要改变ui的变量类型。如何降低耦合性。?

interface UserInfoDao//接口

{

public void add(User user);

public void delete(User user);

}

class UserInfoByJDBC implements UserInfoDao

{

pulic void add(User user)//覆盖接口

{

1,JDBC连接数据库。;

2,使用sql添加语句添加数据。;

3,关闭连接。

}

pulic void delete(User user)

{

1,连JDBC接数据库。;

2,使用sql添加语句删除数据。;

3,关闭连接。

}

}

class DBOperate

{

public static void main(String[] args)

{

UserInfoDao ui=new UserInfoByJDBC();

ui.add(user);

ui.delete(user);

}

}

 

 

105_面向对象(Object类-equals())

object是所有对象的直接后者间接父类,传说中的上帝

该类中定义的肯定是所有对象都具备的功能。

class Demo//隐藏了extends object

{

Demo()

{

//隐藏了super();

}

 

java中,任何对象具比较两个对象是否相同的功能:equals

class Demo

{

 

}

class ObjectDemo

{

public static void main(Stringp[] args)

{

Demo d1=new Demo();

Demo d2=new Demo();

Demod3=d1;//d3是媒介

System.out.println(d1.equals(d2));打印false

System.out.println(d1.equals(d3));打印true。这个equals接受的是Demo类型

System.out.println(d1==d2);打印false。其实equals其实相当于比较地址值

System.out.println(d1==d3);打印true

 

Person p1=new Person();

Person p2=new Person();

system.out.println(people+p1.equals(p2));打印people:true。这个equals接受是Person类型

}

}

}

Person类型和Demo类型都是object的子民。

equals(Object obj)定义object的类型,故它的子民都是可以调用它。

 

class Demo

{

private int num;

Demo(int num)//构造函数

{

this.num=num;

}

public boolean compare(Demo d)

{

return this.num==d.num;比较的是数值而不是地址

}

}

class ObjectDemo

{

public static void main(Stringp[] args)

{

Demo d1=new Demo(4);

Demo d2=new Demo(6);

System.out.println(d1.compare(d2));//false

}

}

}

Object中已经提了对对象是否相同的比较方法。

如果自定义类中也有比较相同的功能时,没有必要重新定义。

只要沿袭父类中的功能,建立自己特有比较内容即可。这就是覆盖

 

class Demo

{

private int num;

Demo(int num)

{

this.num=num;

}

public boolean equals(Objectobj)

{

return this.num==obj.num;//变量num在Object的类中,找不到

}

class ObjectDemo

{

public static void main(Stringp[] args)

{

Demo d1=new Demo(4);

Demo d2=new Demo(6);

System.out.println(d1.equals(d2));//编译错误

}

}

}

 

class Demo

{

private int num;

Demo(int num)

{

this.num=num;

}

public boolean equals(Object obj)此时把Object obj=d2;相当于Objectobj=new Demo();这时相当于多态的表现形式。

{

Demo d=(Demo)obj;//把上帝类Object的obj对象,强制转换为Demo型

return this.num==d.num;//这时,就可以调用d.num

}

class ObjectDemo

{

public static void main(Stringp[] args)

{

Demo d1=new Demo(4);

Demo d2=new Demo(4);

System.out.println(d1.equals(d2));//打印true

}

}

 

class Demo

{

private int num;

Demo(int num)

{

this.num=num;

}

public boolean equals(Object obj)

{

Demo d=(Demo)obj;

return this.num==d.num;

}

class ObjectDemo

{

public static void main(Stringp[] args)

{

Demo d1=new Demo(4);

Demo d2=new Demo(5);

Person p=new Person();

System.out.println(d1.equals(p));//运行报错。ClassCastException类型转换异常

}

}

 

class Demo

{

private int num;

Demo(int num)

{

this.num=num;

}

publicboolean equals(Object obj)//这个是复写(覆盖),因为在父类Object中已经存在了public booleanequals(Object obj)方法了。

{

if(!(obj instanceof Demo))//instanceofobj指向的是Demo吗?不是,返回false

return false;

Demo d=(Demo)obj;

return this.num==d.num;  

}

class ObjectDemo

{

public static void main(Stringp[] args)

{

Demo d1=new Demo(4);

Demo d2=new Demo(5);

Person p=new Person();

System.out.println(d1.equals(p));打印false

}

}

 

class Demo

{

private int num;

Demo(int num)

{

this.num=num;

}

public boolean equals(Object obj)//这个是复写(覆盖),因为在父类Object中已经存在了public booleanequals(Object obj)方法了。

{

if(!(obj instanceof Demo))//instanceofobj指向的是Demo吗?不是,返回false

return false;

Demo d=(Demo)obj;

return this.num==d.num;  

}

class ObjectDemo

{

public static void main(Stringp[] args)

{

Demo d1=new Demo(4);

Demo d2=new Demo(5);

Person p=new Person();

System.out.println(d1.equals(p));//编译通过,打印false。

}

}

 

 

106_面向对象(Object类toString())

toString()函数:java中,任意对象都可以变成字符串打印

class Demo

{

private int num;

Demo(int num)

{

this.num=num;

}

public boolean equals(Object obj)//这个是复写(覆盖),因为在父类Object中已经存在了public booleanequals(Object obj)方法了。

{

if(!(obj instanceof Demo))//instanceofobj指向的是Demo吗?不是,返回false

return false;

Demo d=(Demo)obj;

return this.num==d.num;  

}

class ObjectDemo

{

public static void main(Stringp[] args)

{

Demo d1=new Demo(4);

Demo d2=new Demo(5);

System.out.println(d1.toString());//打印Demo@c17164。即打印对象d1所属的Demo和连接符号@,以及这个对象的哈希值

}

}

 

Object中有专门打印哈希值的函数hashCode()

class ObjectDemo

{

public static void main(Stringp[] args)

{

Demo d1=new Demo(4);

Demo d2=new Demo(5);

System.out.println(d1.toString());//打印Demo@c17164。显示对象d1所属的类Demo和@,这个对象的哈希值

System.out.println(d1.hashCode());//打印12677476

}

 

把打印的值强制转换为16进制

class ObjectDemo

{

public static void main(Stringp[] args)

{

Demo d1=new Demo(4);

Demo d2=new Demo(5);

System.out.println(d1.toString());//打印Demo@c17164。显示对象d1所属的类Demo和@,这个对象的哈希值

System.out.println(Integre.toHexString(d1.hashCode()));//打印c17164

}

}

 

class ObjectDemo

{

public static void main(String[] args)

{

Demo d1=new Demo(4);

Class c=d1.getClass();//c获取d1对象所属的Demo

System.out.println(c.getName());//打印Demo。getName()返回c的名称

}

 

class ObjectDemo

{

public static void main(Stringp[] args)

{

Demo d1=new Demo(4);

Class c=d1.getClass();//c获取d1对象所属的类Demo

System.out.println(c.getName()+@+Integer.toHexString(d1.hashCode()));//打印Demo@c17164

System.out.println(d1.toString);//Demo@c17164

}

总结:

toString()相当于

getClass().getName() + '@' +Integer.toHexString(hashCode())

 

class Demo

{

private int num;//num私有化

Demo(int num)//提供num的访问方式

{

this.num=num;

}

public boolean equals(Object obj)//这个是复写(覆盖),因为在父类Object中已经存在了public booleanequals(Object obj)方法了。

{

if(!(obj instanceof Demo))//instanceofobj指向的是Demo吗?不是,返回false

return false;

Demo d=(Demo)obj;

return this.num==d.num;  

}

class StringtoString()//复写(覆盖)原来的toString()

{

return demo+num;//这里+是连接符

}

class ObjectDemo

{

public static void main(String[] args)

{

Demo d1=new Demo(4);

System.out.println(d1.toString());//打印demo4。

Demo d2=new Demo(5);

}

}

0 0
原创粉丝点击