Chapter 8 Polymorphism

本文通过实例详细解析了Java中的多态性及其优先级,并探讨了抽象类的作用及其实现方式。作者通过对比面向过程与面向对象的编程思路,深入浅出地解释了多态如何工作以及在什么场景下使用抽象类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. Overview

看到书中的例子我以为我都懂了,不过看到了一个例子之后,才发现我都是半懂,没有仔细思考,看书的时候心不静。关于多态有一个优先级可以概括,详见http://blog.youkuaiyun.com/thinkghoster/archive/2008/04/19/2307001.aspx。优先级由高到低依次为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。

  1. Example and research

 

class A {
         
public String show(D obj){
                
return ("A and D");
         } 
         
public String show(A obj){
                
return ("A and A");
         } 

class B extends A{
         
public String show(B obj){
                
return ("B and B");
         }
         
public String show(A obj){
                
return ("B and A");
         } 
}
class C extends B{} 
class D extends B{} 

以下是结果

        A a1 = new A();
        A a2 = 
new B();
        B b = 
new B();
        C c = 
new C(); 
        D d = 
new D(); 
        System.out.println(a1.show(b));  

        System.out.println(a1.show(c));  

        System.out.println(a1.show(d));  

        
System.out.println(a2.show(b));  
        System.out.println(a2.show(c));  

        System.out.println(a2.show(d));  

        System.out.println(b.show(b));    
        System.out.println(b.show(c));     

        
System.out.println(b.show(d));        

 

其中4,5,6,9全部做错。那就一个一个验证这个优先级吧。

  1. System.out.println(a2.show(b))

    之前看过书中有这样的例子:

import java.util.*;

 

class Shape {

void draw() {System.out.println("Shape.draw()");}

void erase() {}

}

 

class Circle extends Shape {

void draw() {

System.out.println("Circle.draw()");

}

void erase() {

System.out.println("Circle.erase()");

}

}

 

class Square extends Shape {

void draw() {

System.out.println("Square.draw()");

}

void erase() {

System.out.println("Square.erase()");

}

}

 

class Triangle extends Shape {

void draw() {

System.out.println("Triangle.draw()");

}

void erase() {

System.out.println("Triangle.erase()");

}

}

 

// A "factory" that randomly creates shapes:

class RandomShapeGenerator {

private Random rand = new Random();

public Shape next() {

switch(rand.nextInt(3)) {

default:

case 0: return new Circle();

case 1: return new Square();

case 2: return new Triangle();

}

}

}

 

public class Shapes {

private static RandomShapeGenerator gen =

new RandomShapeGenerator();

public static void main(String[] args) {

Shape[] s = new Shape[9];

// Fill up the array with shapes:

for(int i = 0; i < s.length; i++)

s[i] = gen.next();

// Make polymorphic method calls:

for(int i = 0; i < s.length; i++){

s[i].draw();

};

}

}

 

结果如下:

Square.draw()

Circle.draw()

Triangle.draw()

Triangle.draw()

Triangle.draw()

Circle.draw()

Square.draw()

Triangle.draw()

Circle.draw()

每一个父类Shape引用的都是子类,输出的也都是子类的方法。所以我以为对于4中应该输出"B AND B"。但是注意到调用的方法在父类中一个在父类中定义过了,一个没有。什么意思?如果在类A中加上这么一段:

public String show(B obj){

return ("A and BB");

}

那么4的结果就是"B AND B"。这是类A和B中都有一个同样的方法show(B obj)。那为什么4的结果是"B AND A"了?注意到刚才说的优先级,首先查找this.show(),这是是没有对应的方法的。接着查找super.show(),super.show是没有的,因为a2的定义是A a2 = new B(),a2还是一个类型为a的引用变量。接着查找this.show((super)O),这样就找到了对应的方法了,为类A中的show(A object)方法,但是注意子类B中有方法把他给覆盖了!所以使用的类B中的方法!结果为"B and A"

其他的都同理可以论证了。

  1. My thinking in java

    加上了多态后,立刻变的复杂了。从面向过程转到面向对象我还非常不习惯,习惯于参数必须和声明的参数类型完全一样。有了多态和抽象类到底有什么好处,为什么要引入这两个东西了?

  • 抽象类

    我觉得抽象类主要是提高代码的可读性,如果没有抽象类也一样可以实现这样的功能。比如在父类中的方法实现就写为空,然后在子类中覆盖就行了,加上了abstract之后只不过加上了语法的检查。

  • 多态和继承

    多态是一个利器,不过很有可能让代码变的更糟糕。父类和子类有三种情况:

  1. 父类方法比子类多

    这种情况下公共的接口最好用abstract,父类中多出来的方法,作为所有子类的公共方法使用设置为Public让子类继承。

  2. 父类方法和子类一样多

    这个时候最好父类的方法都用来继承,提供公共的接口。

  3. 父类方法少于子类

    相同的部分作为公共接口,子类中多出来的方法可以用downcasting。

    这样定义类时都可以用父类的引用使用子类方法。

    

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值