在布鲁斯·埃克尔(Bruce Eckel)在Java 8上给出的示例中,内部班级似乎不必

发布于 2025-01-30 19:59:00 字数 2612 浏览 5 评论 0原文

布鲁斯·埃克尔(Bruce Eckel)在Java 8上的书的内部分类中给出了以下示例,以证明使用内部类而不是实现接口的必要性。但是我发现代码在没有内部类的情况下正常工作。如果您仅实现CalLee2的可增量接口,则代码似乎会编译并给出相同的结果。布鲁斯·埃克尔(Bruce Eckel)给出了不适当的例子,还是我错过了什么?

package innerclasses;

interface Incrementable {
    void increment();
}

// Very simple to just implement the interface:
class Callee1 implements Incrementable {
    private int i = 0;
    
    @Override
    public void increment() {
        i++;
        System.out.println(i);
    }
}

class MyIncrement {
    public void increment() {
        System.out.println("Other operation");
    }
    
    static void f(MyIncrement mi) {
        mi.increment();
    }
}

// If your class must implement increment() in
// some other way, you must use an inner class:
//Why not just implement Incremetable??? I don't get it
class Callee2 extends MyIncrement {
    private int i = 0;
    
    @Override
    public void increment() {
        super.increment();
        i++;
        System.out.println(i);
    }
    
    private class Closure implements Incrementable {
        @Override
        public void increment() {
            // Specify outer-class method, otherwise
            // you'll get an infinite recursion:
            Callee2.this.increment();
        }
    }
    
    Incrementable getCallbackReference() {
        return new Closure();
    }
}

class Caller {
    private Incrementable callbackReference;
    
    Caller(Incrementable cbh) {
        callbackReference = cbh;
    }
    
    void go() {
        callbackReference.increment();
    }
}

public class Callbacks {
    public static void main(String[] args) {
        Callee1 c1 = new Callee1();
        Callee2 c2 = new Callee2();
        MyIncrement.f(c2);
        Caller caller1 = new Caller(c1);
        Caller caller2 = new Caller(c2.getCallbackReference());
        caller1.go();
        caller1.go();
        caller2.go();
        caller2.go();
    }
}

输出:

Other operation
1
1
2
Other operation
2
Other operation
3

为什么不只是实现Callee2类的可增量接口?我尝试了,它似乎很好。

...
class Callee2 extends MyIncrement implements Incrementable{
    ...
    // everything remains the same just comment out the inner class 
    // closure
}

布鲁斯·埃克尔(Bruce Eckel)在书中说:

这显示了在外部类中实现接口与在内部类中这样做之间的进一步区别。就代码而言,Callee1显然是更简单的解决方案。 CalLee2从MyIncrement继承,它已经具有不同的增量()方法,该方法与可增量接口所期望的一个无关。 当将肌输入继承到callee2中时,递增()不能被覆盖以通过增量使用,因此您不得不使用内部类提供单独的实现。 < /p>

i没有看到为什么我被迫使用内部类,因为实现界面提供了完全相同的输出,因此我 使用内部类。您能否解释没有内部类别的代码的行为可能会有所不同?

Bruce Eckel gives the following example in Chapter Inner Classed of the book On Java 8 to demonstrate the necessity of using an inner class instead of implementing an interface. But I found the code works fine without the inner class. The code seems to compile and give the same result if you just implement the Incrementable interface for Callee2. Does Bruce Eckel gives an inappropriate example or do I miss something?

package innerclasses;

interface Incrementable {
    void increment();
}

// Very simple to just implement the interface:
class Callee1 implements Incrementable {
    private int i = 0;
    
    @Override
    public void increment() {
        i++;
        System.out.println(i);
    }
}

class MyIncrement {
    public void increment() {
        System.out.println("Other operation");
    }
    
    static void f(MyIncrement mi) {
        mi.increment();
    }
}

// If your class must implement increment() in
// some other way, you must use an inner class:
//Why not just implement Incremetable??? I don't get it
class Callee2 extends MyIncrement {
    private int i = 0;
    
    @Override
    public void increment() {
        super.increment();
        i++;
        System.out.println(i);
    }
    
    private class Closure implements Incrementable {
        @Override
        public void increment() {
            // Specify outer-class method, otherwise
            // you'll get an infinite recursion:
            Callee2.this.increment();
        }
    }
    
    Incrementable getCallbackReference() {
        return new Closure();
    }
}

class Caller {
    private Incrementable callbackReference;
    
    Caller(Incrementable cbh) {
        callbackReference = cbh;
    }
    
    void go() {
        callbackReference.increment();
    }
}

public class Callbacks {
    public static void main(String[] args) {
        Callee1 c1 = new Callee1();
        Callee2 c2 = new Callee2();
        MyIncrement.f(c2);
        Caller caller1 = new Caller(c1);
        Caller caller2 = new Caller(c2.getCallbackReference());
        caller1.go();
        caller1.go();
        caller2.go();
        caller2.go();
    }
}

Output:

Other operation
1
1
2
Other operation
2
Other operation
3

Why not just implement the Incrementable interface for class Callee2? I tried that and it seems to work out fine.

...
class Callee2 extends MyIncrement implements Incrementable{
    ...
    // everything remains the same just comment out the inner class 
    // closure
}

In the book Bruce Eckel says:

This shows a further distinction between implementing an interface in an outer class versus doing so in an inner class. Callee1 is clearly the simpler solution in terms of the code. Callee2 inherits from MyIncrement, which already has a different increment() method that does something unrelated to the one expected by the Incrementable interface. When MyIncrement is inherited into Callee2, increment() can’t be overridden for use by Incrementable, so you’re forced to provide a separate implementation using an inner class.

I didn't see why I'm forced to use inner class since implementing the interface provides the exact same output. Could you please explain how the code may behave differently without the inner class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文