有没有办法避免铸造这种类型?

时间:2014-04-10 18:11:47

标签: java design-patterns protected package-private

考虑以下定义和实现Foo接口的类:

public class MyClass {

    public Foo getFoo() {
        return new FooImpl();
    }

    public void fooMethod(Foo foo) {
        final fooImpl = (FooImpl) foo;
        fooImpl.hiddenMethod();
    }

    public interface Foo {
        void doSomething();
    }

    private class FooImpl implements Foo {
        public void doSomething();

        void hiddenMethod() {
        }
    }
}

外部课程将致电MyClass.getFoo()以获取Foo个对象,并可将其传递回fooMethod()fooMethod()期望FooImpl实施Foo并将Foo转换为FooImpl,以便它可以调用包私有方法hiddenMethod()

我的问题是,我对Foo FooImpl的投射并不感到骄傲。还有其他模式可以用来做同样的事情吗?

提前致谢...

3 个答案:

答案 0 :(得分:3)

这里的问题是你隐含地违反了封装原则。您的类中有一个方法,它取决于实现,因此不属于Foo接口。这违反了OO校长,这个演员阵容只是冰山一角。如果您想设计一个没有想要调用的方法的新Foo实现类,该怎么办?

您应该重新设计代码,以便只能从Foo界面实现此调用方法。

答案 1 :(得分:1)

您可以在hiddenMethod界面

中添加Foo方法
public interface Foo {
    ...   
    void hiddenMethod();
}

由于接口是受支持操作的契约,因此您不需要(不应该)将对象转换为访问接口外部的方法

答案 2 :(得分:0)

你必须贬低。

以这种方式行事

public void fooMethod(Foo foo) {
   if(foo instanceof FooImpl){
      final FooImpl fooImpl = (FooImpl) foo;
      fooImpl.hiddenMethod();
   }
}

超级类型无法在没有明确向下转发的情况下进行向下转换。请务必在使用instanceof运算符进行预测之前进行检查。


- 编辑 -

如果你想避免演员,还要做一件事。在hiddenMethod()界面中添加Foo

public interface Foo {
    void doSomething();
    void hiddenMethod();
}