我现在正在努力挖掘匿名类,刚出现一个问题我不想引用太多细节并直截了当地提出我的问题:如何调用以下方法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()
方法的“关键”是什么?
答案 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();
}
}