为什么匿名类不能实现两个独立的接口但可以实现内部接口?

时间:2015-07-03 18:15:15

标签: java anonymous

匿名类只能从一个类或接口扩展,所以我不能做下一个:

interface Enjoyable {
    public void enjoy();
}

interface Exercisable {
    public void exercise();
}

public class Test {
    public static void main(String[] args) {
        new Enjoyable implements Exercisable() {
            public void enjoy() {
                System.out.println(":D");
            }
        }.enjoy();

    }
}

它说:

  

Enjoyable.Exercisable无法解析为类型

我试图复制这种行为,然后我编写了下一个代码:

interface Enjoyable {
    interface Exercisable {
        public void exercise();
    }
    public void enjoy();
}

public class Test {
    public static void main(String[] args) {
        new Enjoyable.Exercisable() {
            public void enjoy() {
                System.out.println(":D");
            }

            public void exercise() {
                System.out.println("Doing exercise !!!");

            }
        }.exercise();

        new Enjoyable.Exercisable() {
            public void enjoy() {
                System.out.println(":D");
            }

            public void exercise() {
                System.out.println("Doing exercise !!!");

            }
        }.enjoy();

    }
}

然后我得到:

  

做运动!!! :d

还有其他方法可以模拟它吗? 并且我希望在匿名课程中实现两个方法吗?

由于

3 个答案:

答案 0 :(得分:3)

  

我想要一个实现2个接口方法的匿名类

我假设你的意思是你想要一个实现两个接口的匿名类。你不能,直接。

你可以做到

interface EnjoyableAndExercisable extends Enjoyable, Exercisable {
}

然后创建一个实现它的匿名类。

EnjoyableAndExercisable o = new EnjoyableAndExercisable() {
    @Override
    public void enjoy() {
        System.out.println(":D");
    }
    @Override
    public void exercise() {
        System.out.println("Doing exercise !!!");

    }
};

请注意@Override,它将始终验证您是否实际覆盖某个方法。

然而,在你的代码中,这个匿名类

new Enjoyable.Exercisable() {
    public void enjoy() {
        System.out.println(":D");
    }

    public void exercise() {
        System.out.println("Doing exercise !!!");

    }
}.enjoy();

只是Exercisable的一种实现。您恰好在其中声明了一个名为enjoy的方法。

您无法将其分配给Enjoyable

类型的变量
Enjoyable ref = new Enjoyable.Exercisable() {
    public void enjoy() {
        System.out.println(":D");
    }

    public void exercise() {
        System.out.println("Doing exercise !!!");

    }
}; // nope, compile time error

您只能在声明此匿名类型的新实例创建表达式上调用该方法。你不能以任何其他方式调用它(因为它以匿名类型声明)。

答案 1 :(得分:2)

你的可锻炼性并不令人愉快:-) 以这种方式嵌套接口并不意味着内部接口是 外部接口的类型!

你也可以写一些像

这样的东西
data_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']

print [data_list[i::3] for i in range(3)]

#output => [[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9]]

所以你实际上并没有模拟实现两个接口的匿名类。

当您实际尝试将匿名实例分配给接口类型的变量时,您可以看到这一点

new Object() {
            public void enjoy() {
                System.out.println(":D");
            }

            public void exercise() {
                System.out.println("Doing exercise !!!");

            }
        }.enjoy()
// same for .excercise()

你当然可以这样做:

// this WILL NOT COMPILE !
Enjoyable enjoyable=new Enjoyable.Exercisable() {
            public void enjoy() {
                System.out.println(":D");
            }

            public void exercise() {
                System.out.println("Doing exercise !!!");

            }
        }.enjoy();

然后使用这些接口创建匿名实例 不幸的是,创建一个实现两个接口的匿名实例是不可能的。

答案 2 :(得分:0)

您可以根据非final类或带

的接口创建匿名内部类
new Exerciseable(){
...
}

但是,Java不允许

new Object() implements Exercisable{
...
}

new Object implements Exercisable(){
...
}

匿名内部类使用new关键字生成一个类的新实例,该类的超类为Object并实现Exercisable。 JCP站点托管一个文档(https://jcp.org/aboutJava/communityprocess/maintenance/JLS/innerclasses.pdf),属于JSL关于内部类的文件,其中说:

  

如前所述,如果匿名类是从接口派生的   我,实际的超类是Object,而类实现了我   而不是扩展它。 (显式实现子句是非法的。)这是   接口名称可以合法地遵循关键字new的唯一方法。在   在这种情况下,参数列表必须始终为null,以匹配   实际超类的构造函数,Object。

您的第二个示例构建了一个扩展Exercisable的类型Enjoyable。创建该接口的匿名类是合法的。