调用匿名类的子类方法

时间:2012-12-04 22:43:36

标签: java polymorphism inner-classes anonymous-class

我现在正在努力挖掘匿名类,刚出现一个问题我不想引用太多细节并直截了当地提出我的问题:如何调用以下方法sizzle()匿名课程:

public class Popcorn {
    public void pop() {
        System.out.println("popcorn");
    }
}

class Food {
    Popcorn p = new Popcorn() {
        public void sizzle() {
            System.out.println("anonymous sizzling popcorn");
        }

        public void pop() {
            System.out.println("anonymous popcorn");
        }
    };

    public void popIt() {
        p.pop(); // OK, Popcorn has a pop() method
        p.sizzle(); // Not Legal! Popcorn does not have sizzle()
    }
}

在多态性规则中已知且明确的是,超类的引用不能在没有向下转换的情况下调用子类的方法(即使它引用给定子类的对象)。但是在上面的例子中,调用sizzle()方法的“关键”是什么?

3 个答案:

答案 0 :(得分:2)

无法从外部访问sizzle()方法,因为该类是匿名的。

p引用是Popcorn类型,并未定义sizzle()

匿名类是一次性的,并且在一些设计模式(如 Observer )中大量使用,因为Java没有第一类函数,即你不能传递函数对象周围。

答案 1 :(得分:2)

我有点没想到这会起作用,但确实如此:

new Object() {
    public void foo() {}
}.foo();

以上将按预期编译和工作。解释是表达式 new Object() {}的类型是表达式定义的匿名类型,而不是Object。但是,您不能拥有该类型的变量(或方法参数),这意味着您无法在new表达式之后的其他任何位置调用该方法。

由于这并没有真正解决你的(无法解决的)问题,我承认这更像是一个补充答案。

答案 2 :(得分:1)

当您致电p.sizzle()时,您需要让p变量属于具有sizzle()方法的类型。 唯一的方法是使用子类或接口。 如果你不想改变p的类型,你甚至可以施放,但你不能施放到匿名类型。

如果您只在Food类中需要该类,则应在其中声明

class Food {
    EdiblePopcorn p = new EdiblePopcorn() {

        @Override
        public void sizzle() {
            System.out.println("anonymous sizzling popcorn");
        }

        @Override
        public void pop() {
            System.out.println("anonymous popcorn");
        }
    };

    public void popIt() {
        p.pop(); // OK, Popcorn has a pop() method
        p.sizzle(); // Also legal! EdiblePopcorn now has sizzle()
    }

    private abstract class EdiblePopcorn extends Popcorn {
        // if the sizzle body is always the same, you can declare it here.
        void sizzle();
    }
}