java的多态

多态性是OOP中的重要特性,在java中,多态性主要通过重载和重写两种方式实现。

当一个父类有多个子类,通过多态可正确地调用不同子类的方法:

class Shape{
    public void draw(){
        System.out.println("draw a shape");
    }
}

class Square extends Shape{
    @Override
    public void draw() {
        System.out.println("draw a square");
    }
}

class Circle extends Shape{
    @Override
    public void draw() {
        System.out.println("draw a circle");
    }
}

class PolyTest{
    public static void main(String[] args) {
        
        Shape[] shapes=new Shape[10];
        for (int i = 0; i < shapes.length; i++) {
            shapes[i]=new Random().nextInt(2)==0?new Square():new Circle();
        }
        
        for (Shape shape : shapes) {
            shape.draw();
        }
    }
}


/*
output:
draw a square
draw a circle
draw a square
draw a circle
draw a circle
draw a square
draw a square
draw a circle
draw a square
draw a circle
*/

 


 

但是也有需要注意的地方,如当父类的变量和方法为私有时:

class Super {
    private String name = "private name";

    private void func() {
        System.out.println("private function");
    }

    public static void main(String[] args) {
        Super sup = new Sub();
        sup.func();
        System.out.println(sup.name);
    }
}

class Sub extends Super {
    public String name = "public name";

    public void func() {
        System.out.println("public function");
    }
}

/*
 * output: 
private function
private name
 */

结果并不是我们所认为的“public function public name”。因为父类的私有成员对子类是屏蔽的,无法被重写,所以jvm直接调用父类的func方法,不会再检查子类,即使子类中拥有同名方法,也会被认为是新的方法。

为了避免出错,最好不要在子类中出现与父类私有成员同名的成员,以免被误导。


 

再来看一个例子:

class Super {
    public String name = "super name";

    public String getName() {
        return name;
    }
}

class Sub extends Super {
    public String name = "sub name";

    public String getName() {
        return name;
    }

    public String getSupName() {
        return super.name;
    }
}

class PolyTest {
    public static void main(String[] args) {
        Super sup = new Sub();
        System.out.println("sup name:" + sup.name + ";sup.getName:" + sup.getName());
        Sub sub = new Sub();
        System.out.println(
                "sub name:" + sub.name + ";sub.getName:" + sub.getName() + ";sub.getSupName:" + sub.getSupName());

    }
}

/*
output:
    
sup name:super name;sup.getName:sub name
sub name:sub name;sub.getName:sub name;sub.getSupName:super name
*/

当子类对象向上转型为父类对象,并直接调用成员变量时,调用的是父类的成员变量;调用的成员方法还是子类的成员方法。

所以在继承过程中,如果成员变量可能要被覆盖,最好将其设置为private,并用get,set方法来对其进行操作,这种方法在很多情况下都会用到,例如在封装新的数据类型时。

 

posted @ 2016-03-14 18:37  maozs  阅读(235)  评论(0编辑  收藏  举报