——- android培训、java培训、期待与您交流! ———-
一 多态
1. 多态的概念:
什么是多态:多态是同一个行为具有多个不同表现形式或形态的能力。可以理解为,事物存在的多中体现形态.
一个对象只有一个格式(是在构造时给它的)。但是,既然变量能指向不同格式的对象, 那么变量就是多态性的。也就是说一个对象只有一种形式,但一个变量却有多种不同形式。 象大多数面向对象语言一样,Java 实际上允许父类类型的引用变量指向一个子类的对象。
对象的多态性
人:男人 女人
动物:猫、狗
猫 x = new 猫();
动物 x = new 猫();
那么动物就是猫和狗具体事物中抽取出来的父类型。父类型引用指向了子类对象。
重载和覆盖是函数多态的体现
1 多态的基本体现
父类的应用指向了自己 的子类对象
父类的应用也可以接收机子的子类对象
2 多态的前提
必须是类与类之间有关系 要么继承 要么实现
通常还有一个前提 存在覆盖
3 多态的好处
多态的出现大大的提高了代码的拓展性
4 多态的特特点
5 多态的弊端
提高了拓展性 但是只能使用父类的引用访问父类中的成员
6 多态的出现代码中的特点(多态的注意事项)
—拓展性
想要调用猫的特有方法时,如何操作
向下转型 使用特有方法
强制将父类的 引用 转成子类类型
我们能转换的是父类的引用指向自己的子类对象时.该引用可以提升,也可以被强制转换
注意:不能将父类对象转成子类类型
多态自始至终都是子类对象在做变化
如下面的例子:
/*
动物 猫狗
*/
//抽象出动物的共性--吃的特性
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("看家");
}
}
//主类
class DT
{
public static void main(String[] args)
{
// Cat c = new Cat();
// Dog d = new Dog();
//Animal a = new Cat();//类型提升 向上转型
//a.eat();
fun(new Cat());
fun(new Dog());
//想要调用猫的特有方法时,如何操作
//向下转型 使用特有方法
//强制将父类的!引用! 转成子类类型
//Cat c = (Cat) a ;
//c.catchMouse();
}
public static void fun(Animal a)
{
a.eat();
if(a instanceof Cat)
{
Cat c = (Cat)a;
c.catchMouse();
}
if(a instanceof Dog)
{
Dog c = (Dog)a;
c.kanjia();
}
}
}
运行结果
————割———————————–割——————–
2. 多态的应用:
- 多态中,成员函数的特点
在编译时:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过
在运行时,参阅对象所属类中是否有调用的方法
总结就是:
成员函数在多态调用时 编译看左边 运行看右边
多态中,成员变量的特点
无论编译和运行都参考左边(引用型变量所属的类)在多态中,静态成员函数的特点
无论编译和运行,都参考左边
下面来看一个多态的实际应用:
电脑的运行实例。电脑的运行由主板控制,
假设主板只是提供电脑运行,但是没有上网,听歌等功能。而上网、听歌需要硬件的支持。而现在主板上没有网卡和声卡,这时可以定义一个规则,叫PCI,只要符合这个规则的网卡和声卡都可以在主板上使用,
这样就降低了主板和网卡、声卡之间的耦合性。用程序体现。
/*
需求:电脑运行示例
电脑运行基于主板
*/
//用接口描述PCI规则
interface PCI
{
public void open();
public void close();
}
//主板
class MainBoard
{
public void run()
{
System.out.println("Mainboard running");
}
//这里用到了多态的知识
public void usePCI(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("soundcard open");
}
public void close()
{
System.out.println("soundcard close");
}
}
//主类
class MotherBoard
{
public static void main(String[] args)
{
MainBoard mb = new MainBoard();
mb.run();
mb.usePCI(new NetCard());
mb.usePCI(new SoundCard());
}
}
运行结果
————割———————————–割——————–
二 equals 和 toString
Object 所有对像的直接或者间接父类 传说中的上帝
该类中定义的肯定是所有对象都具有的功能
Object 类中已经提供了对对像是否相同的比较方法
如果自定义类中也有比较相同的功能,建立自己特有比较内容即可, 这就是覆盖.
看下面的实例代码:
//每个类都默认继承Object类
class Demo//extends Object
{
private int num;
Demo (int num)
{
this.num = num;
}
//覆盖equals 方法
public boolean equals(Object obj)//Object obj = new Demo()
{
if(!(obj instanceof Demo))
return false;
Demo d = (Demo) obj;
return this.num==d.num;
}
//重写toString 方法
public String toString()
{
return "Demo"+num;
}
}
class ObjectDemo
{
public static void main(String[] args)
{
Demo d1 = new Demo(5);
Demo d2 = new Demo(5);
System.out.println(d1.toString());//如果注释掉toString方法,那么这句的结果是Demo@1fb9ee3(hashCode)
System.out.println(d1.equals(d2));//重写之后是内容相等才返回true. 因为如果没有重写,父类的equals比较的是两块内存是否一样,如果一样则返回true,否则为返回false.
}
运行结果: