1.问题提出
abstract class Animals {
public abstract void eat();
}
class Cat extends Animals {
public void eat() {
System.out.println("cat eat");
}
}
class Dog extends Animals {
public void eat() {
System.out.println("Dog eat");
}
}
class FeedPerson {
public void Feed(Dog g) {
g.eat();
}
public void Feed(Cat c) {
c.eat();
}
}
public class EatDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
FeedPerson fb = new FeedPerson();
Cat c = new Cat();
Dog g = new Dog();
fb.Feed(c);
fb.Feed(g);
}
}
常规做法,我们先创建一个抽象类动物类,再让猫狗类继承动物类,实现动物类中的抽象方法
但是,问题来了!
如果我们有很多种动物,猪狗兔子狮子,我们是不是要在工具类FeedPerson中添加那么多的Feed方法呢?
这时,我们本场的主角出场了多态
abstract class Animals {
public abstract void eat();
}
class Cat extends Animals {
public void eat() {
System.out.println("cat eat");
}
}
class Dog extends Animals {
public void eat() {
System.out.println("Dog eat");
}
}
class FeedPerson {
/*public void Feed(Dog g) {
g.eat();
}
public void Feed(Cat c) {
c.eat();
}*/
public void Feed(Animals a) {
a.eat();
}
}
public class EatDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
FeedPerson fb = new FeedPerson();
// Cat c = new Cat();
// Dog g = new Dog();
Animals c = new Cat();
Animals g = new Dog();
fb.Feed(c);
fb.Feed(g);
}
}
2.多态的体现
- 有继承关系
- 有方法重写
- 有父类指向子类对象
3. 成员访问特点
-
成员变量
编译看左边,运行看左边
-
成员方法
编译看左边,运行看右边
-
静态方法
编译看左边,运行看左边
所以说静态方法不能算方法的重写
看左边看右边???什么意思??看代码
class Fu
{
int age = 44;
public void show()
{
System.out.println("fu show");
}
public void method()
{
System.out.println("fu method");
}
}
class Zi extends Fu
{
int age = 18;
public void show()
{
System.out.println("zi show");
}
public void method()
{
System.out.println("zi method");
}
}
class Test
{
public static void main(String[] args)
{
Fu f = new Zi();
/*
成员方法
*/
//f.method(); //编译看有左边,由于Fu中没有mechod()方法所有抱错
f.show(); //运行看右边,输出Zi类的show方法
/*
成员变量
*/
System.out.println(f.age); //运行看有左边,执行看左边,输出44
}
}
OutPut:
zi show
44
- 向上转型
从子到父
父类引用指向子类对象
Animal a = new Cat();
- 向下转型
从父到子
父类引用转为子类对象
Cat c = (Cat)a; //(Cat)Animal a
- 如何判断转型是否正确
从右往左读,看是否通顺
class Animal{}
class Dog extends Animal{}
class Cat extends Animal{}
Animal p0 = new Animal();
Dog p1 = new Dog ();
Cat p2 = new Cat ();
Animal p3 = new Dog ();
Animal p4 = new Cat ();
p0 = p1; //Animal p0 = Dog p1 🐖猪是动物 true
p1=p0 // Dog p1 = Animal p0 动物是🐖 猪false
p1 = p2; //Dog p1 = Cat p2 🐱猫是🐕狗 false
p1 = (Dog)p3; //Animal向下转型true
p2 = (Cat)p4; //Animal向下转型true
4.执行顺序
执行顺序例子:
```java
class A {
public void show() {
show2();
}
public void show2() {
System.out.println("我");
}
}
class B extends A {
/*
public void show() {
show2();
}
*/
public void show2() {
System.out.println("爱");
}
}
class C extends B {
public void show() {
super.show();
}
public void show2() {
System.out.println("你");
}
}
public class DuoTaiTest4 {
public static void main(String[] args) {
A a = new B();
a.show();
//B的show方法->没有
//->找父类A的show方法->找B的show2方法(而不是找A的,优先找自己的)->爱
B b = new C();
b.show();
//同理C的show方法->找父类A的show方法->C的show2方法
}
}
/*
输出:
爱
你
*/
拓展
静态代码块,构造代码块,成员方法代码块,优先级执行顺序如何?
package Duotai;
/*
* 静态代码块
* 构造代码块
* 构造方法
* 执行顺序*/
class AA{
static {
System.out.println("static block");
}
{
System.out.println("construct block");
}
public AA(){
System.out.println("AA");
}
}
class BB extends AA{
static {
System.out.println("static block");
}
{
System.out.println("construct block");
}
public BB(){
System.out.println("BB");
}
}
public class Fellow {
public static void main(String[] args) {
BB b = new BB();
}
}
/*
Astatic block
Bstatic block
Aconstruct block
AA
Bconstruct block
BB
*/
可见静态代码块优先于所有代码块,且父类优先于子类,构造代码块其次
,构造方法最后
5.小结
多态提高了程序的扩展性,但是父类不能调用子类特有的功能