概念
实物存在的多种体现形态。
多态的体现
父类的引用指向了自己的子类对象,即父类的引用也可以接收自己的子类对象。
多态的前提
必须是类与类之间有关系,要么继承,要么实现;
通常还有一个前提:存在覆盖。
多态的好处
提高了程序的扩展性。
多态的弊端
只能使用父类的应用访问父类中的成员。
/*
吃鱼
捉老鼠
吃骨头
*/
abstract class Animal
{
abstract void eat();
}
class Cat extends Animal
{
void eat()
{
System.out.println("吃鱼");
}
void catchMouse()
{
System.out.println("捉老鼠");
}
}
class Dog extends Animal
{
void eat()
{
System.out.println("吃骨头");
}
}
class Pig extends Animal
{
void eat()
{
System.out.println("吃饲料");
}
}
public class Demo
{
public static void main(String[] args) {
Animal a = new Cat();//类型提升/向上转型
function(a);
function(new Dog());
//如果需要调用猫的特有方法时,如何操作?强制将父类的引用转成子类类型,即向下转型
//注意不要将父类对象转成子类类型,我们能转换的是父类应用指向自己的子类对象时,该应用可以被提升,也可以被转换。自始至终都是子类对象在做着变化。
//Animal aa = new Animal();
//Cat cc = (Cat)aa;
Cat c = (Cat)a;//向下转型
}
public static void function(Animal a)
{
a.eat();
if(a instanceof Cat)
{
Cat c = new Cat();
c.catchMouse();
}
}
}
多态示例
abstract class Person
{
void sleep()
{
System.out.println("sleep");
}
abstract void work();
}
class Student extends Person
{
void work()
{
System.out.println("学习");
}
}
class Worker extends Person
{
void work()
{
System.out.println("工作");
}
}
class DoPerson
{
void doSomething(Person p)
{
p.sleep();
p.work();
}
}
public class Demo
{
public static void main(String[] args)
{
DoPerson dp = new DoPerson();
dp.doSomething(new Student());
dp.doSomething(new Worker());
/*Student s = new Student();
s.sleep();
s.work();
Worker w = new Worker();
w.sleep();
w.work();*/
}
}
多态中成员的特点
- 多态中成员函数的特点
在编译期间:参阅引用型变量所属类中是否有调用的方法,如果有编译通过,如果没有编译失败;
在运行期间:参阅对象所属的类中是否有调用的方法。
简单总结来说,成员函数在多态调用时,编译看左边,运行看右边。
注意:这里的成员函数是非静态成员函数,如果是静态成员函数的话,运行左边。 - 多态中成员变量的特点(包含静态)
无论编译和运行,都参考左边(引用型变量所属的类)。 - 多态中成员函数的特点
无论编译和运行,都参考左边。
/*
Zi method1
5
15
*/
class Fu
{
int num = 5;
void method1()
{
System.out.println("Fu method1");
}
}
class Zi extends Fu
{
int num = 15;
void method1()
{
System.out.println("Zi method1");
}
void method2()
{
System.out.println("Fu method2");
}
}
public class Demo
{
public static void main(String[] args)
{
Fu f = new Zi();
f.method1();
System.out.println(f.num);
Zi z = new Zi();
System.out.println(z.num);
//f.method2(); 编译出错
}
}
多态结合接口
/*
mainboard open!
mainboard close!
NetCard open!
NetCard close!
SoundCard open!
SoundCard close!
*/
interface PCI
{
void open();
void close();
}
class MainBoard
{
void open()
{
System.out.println("mainboard open!");
}
void close()
{
System.out.println("mainboard close!");
}
void usePCI(PCI pci)//多态
{
if(pci != null) {
pci.open();
pci.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!");
}
}
public class Demo
{
public static void main(String[] args)
{
MainBoard m = new MainBoard();
m.open();
m.close();
m.usePCI(new NetCard());
m.usePCI(new SoundCard());
}
}
Object类equals()
是所有对象的直接或者间接父类,该类中定义的是所有对象都具备的功能。
Object类中已经提供了对对象是否相同的比较方法,如果自定义类中也有比较相同的功能,没有必要重新定义,只要沿袭父类中的功能,建立自己特有的比较内容即可,这就是覆盖。
class Person//extends Object
{
private int num;
Person(int num)
{
this.num = num;
}
public boolean equals(Object obj)//覆盖
{
if(obj instanceof Person)
{
Person p = (Person)obj;//向下转型
return p.num == this.num;
}
else
return false;
}
}
public class Demo
{
public static void main(String[] args)
{
Person p = new Person(4);
System.out.println(p.equals(new Person(4)));
}
Object类toString()
/*
Person@@135fbaa4
Person@135fbaa4
*/
public class Demo
{
public static void main(String[] args)
{
Person p = new Person();
Class c = p.getClass();
System.out.println(c.getName() + "@@" + Integer.toHexString(p.hashCode()));
System.out.println(p.toString());
}
}
class Person
{
void show()
{
System.out.println("Person");
}
}
复习题
//a
public class Demo {
public static void main(String[] args) {
new Person().printPerson();
new Student().printPerson();
}
}
class Student extends Person {
@Override
public String getInfo() {
return "Student";
}
}
class Person {
public String getInfo() {
return "Person";
}
public void printPerson() {
System.out.println(getInfo());
}
}
//b
public class Demo {
public static void main(String[] args) {
new Person().printPerson();
new Student().printPerson();
}
}
class Student extends Person {
private String getInfo() {
return "Student";
}
}
class Person {
private String getInfo() {
return "Person";
}
public void printPerson() {
System.out.println(getInfo());
}
}
a:
/*
Person
Student
*/
b:
/*
Person
Person
*/
public class Demo {
public static void main(String[] args) {
new A();
new B();
}
}
class A {
int i = 7;
public A() {
setI(20);
System.out.println("i from A is " + i);
}
public void setI(int i) {
this.i = 2 * i;
}
}
class B extends A {
public B() {
System.out.println("i from B is " + i);
}
public void setI(int i) {
this.i = 3 * i;
}
}
/*
i from A is 40
i from A is 60
i from B is 60
*/