多态
可以理解为事物存在的多种体现形式
人:男人,女人
动物:猫,狗
猫 x = new 猫();
动物 x = new 猫();
1,多态的体现
父类的引用指向了自己的子类对象。
父类的引用也可以接收自己的子类对象
2,多态的前提
必须是类与类之间有关系,要么继承,要么实现。
通常还有一个前提,就是存在覆盖。
3,多态的好处
多态的出现,提高了程序的扩展性
弊端:只能使用父类的引用访问父类中的成员
abstract class Animal
{
abstract void eat();
{
System.out.println("睡觉");
}
}
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("wangwang");
}
}
class Pig extends Animal
{
public void eat()
{
System.out.println("饲料");
}
public void gongdi()
{
System.out.println("拱地");
}
}
class DuoTaiDemo
{
public static void main(String[] args)
{
function(new Cat());
function(new Dog());
function(new Pig());
}
public static void function(Animal a)//Animal a = new Cat();多态的体现
{
a.eat();
}
}
构造代码快先执行。
父类引用指向子类对象
Animal a = new Cat();//类型提升,向上转型
a.eat();
如果想要调用猫的特有方法,如何操作?
强制将父类的引用,转成子类类型。向下转型。
Cat c = (Cat)a;
c.catchMouse();
千万不要出现这样的操作,就是将父类对象转成子类类型。
我们能转换的是父类引用指向自己子类的对象时,该引用可以被提升,也可以被强制转换。
多态自始至终都是子类对象在做着变化。
Animal a = new Animal();
Cat c = (Cat)a;
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("wangwang");
}
}
class Pig extends Animal
{
public void eat()
{
System.out.println("饲料");
}
public void gongdi()
{
System.out.println("拱地");
}
}
class DuoTaiDemo2
{
public static void main(String[] args)
{
//Animal a = new Cat();//类型提升,向上转型
//a.eat();
//如果想要调用猫的特有方法,如何操作?
//强制将父类的引用,转成子类类型。向下转型。
//Cat c = (Cat)a;
//c.catchMouse();
//千万不要出现这样的操作,就是将父类对象转成子类类型。
//我们能转换的是父类引用指向自己子类的对象时,该引用可以被提升,也可以被强制转换。
//多态自始至终都是子类对象在做着变化。
//Animal a = new Animal();
//Cat c = (Cat)a;
function(new Dog());
function(new Cat());
}
public static void function(Animal a)//Animal a = new Cat();
{
a.eat();
if(a instanceof Cat)//实例是否属于
{
Cat c = (Cat)a;
c.catchMouse();
}
else if(a instanceof Dog)
{
Dog c = (Dog)a;
c.kanjia();
}
else
{
Pig p = (Pig)a;
p.gongdi();
}
}
}
4,多态的应用
基础班
学习,睡觉
高级班
学习,睡觉
可以将这两类事物进行抽取
abstract class Student
{
public abstract void study();
public void sleep()
{
System.out.println("躺着睡");
}
}
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 DoStudent
{
public void dosome(Student stu)
{
stu.study();
stu.sleep();
}
}
class DuoTaiDemo3
{
public static void main(String[] args)
{
DoStudent ds = new DoStudent();
ds.dosome(new BaseStudent());
ds.dosome(new AdvStudent());
}
}
5,多态的出现代码中的特点(多态使用的注意事项)
在多态中成员函数(非静态)的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过。如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用性变量所属的类)。
在多态中,静态成员函数的特点:
无论编译和运行都参考左边。
DuoTaiDemo4
class Fu
{
static int num = 5;//成员变量
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
{
static int num = 8;
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 DuoTaiDemo4
{
public static void main(String[] args)
{
//Fu f = new Zi();
//System.out.println(f.num);
//Zi z = new Zi();
//System.out.println(z.num);//成员变量的特点,编译运行都看左边所属的类
//Fu f = new Zi();
//f.method1();
//f.method2();
//f.method3(); //会编译失败 //成员函数的特点(非静态)编译时看左边,左边类中没有这个方法就失败
Fu f = new Zi();
System.out.println(f.num);
f.method4();
Zi z = new Zi();
z.method4(); //静态成员函数特点,都参考左边
//Zi z = new Zi();
//z.method1();
//z.method2();
//z.method3();
}
}
需求:
电脑运行实例
电脑运行基于主板
interface PCI
{
public void open();
public void close();
}
class MainBoard
{
public void run()
{
System.out.println("mainboard run");
}
public void usePCI(PCI p)//接口型引用指向自己的子类对象
{
if(p!=null)//PCI p = new NetCard()
{
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 DuoTaiDemo5
{
public static void main(String[] args)
{
MainBoard mb = new MainBoard();
mb.run();
mb.usePCI(null);
mb.usePCI(new NetCard());
mb.usePCI(new SoundCard());
}
}
Object类
Object:所有类的直接或间接父类
该类中定义的肯定是所有对象都具备的功能。
class Demo //extends Object
{
}
class ObjectDemo
{
public static void main(String[] args)
{
Demo d1 = new Demo();
Demo d2 = new Demo();
Demo d3 = d1;
System.out.println(d1.equals(d3));
System.out.println(d1==d2);
System.out.println(d1==d3);
}
}
Object中已经提供了对对象是否相同的比较方法。
如果自定义类中也有比较相同的功能,没有必要重新定义,
只要沿袭父类中的功能,建立自己特有的比较内容即可。这就是覆盖。
class Demo //extends Object
{
private int num;
Demo(int num)
{
this.num = num;
}
public boolean equals(Object obj)//Object obj = new Demo();
{
if(!(obj instanceof Demo))//判断是否所属同类
return false;
Demo d = (Demo)obj; //向下转型
return this.num == d.num;
}
}
class ObjectDemo
{
public static void main(String[] args)
{
Demo d1 = new Demo(4);
Demo d2 = new Demo(4);
System.out.println(d1.equals(d2));
}
}
toString
获取对象的哈希值(16进制表现形式)。
class Demo
{
Demo()
{}
}
class ObjectDemo
{
public static void main(String[] args)
{
Demo d = new Demo();
System.out.println(Integer.toHexString(d.hashCode()));
System.out.println(d.toString());
}
}