【问题标题】:Is there any way to avoid casting this type?有什么办法可以避免强制转换这种类型?
【发布时间】:2014-05-24 14:49:48
【问题描述】:

考虑以下定义和实现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。有没有其他模式可以用来做同样的事情?

提前谢谢...

【问题讨论】:

  • 让您的fooMethod 接受FooImpl
  • 为什么Foointerface?通常,当您编写一个接口时,您希望至少在理论上可能有多个类实现它。如果您正在编写一个接口并期望只有一个实现,那么我不得不质疑您为什么将其编写为一个接口。也许有一个很好的理由。但是,如果您解释原因是什么,也许我们可以为您指出组织代码的更好方法。 (P.S. 在 C++ 中以这种方式做事的原因不适用于 Java。)

标签: java design-patterns protected package-private


【解决方案1】:

你必须沮丧。

这样做

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

如果没有明确的向下转换,就不能向下转换超类型。请务必在使用instanceof 运算符进行向下转换之前检查它。


--编辑--

如果您想避免强制转换,请再做一件事。在Foo界面也添加hiddenMethod()

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

【讨论】:

    【解决方案2】:

    您可以将hiddenMethod 方法添加到Foo 接口

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

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

    【讨论】:

      【解决方案3】:

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

      您应该重新设计您的代码,以便您可以从 Foo 接口实现这种仅调用方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-07
        • 2014-05-25
        • 2020-12-29
        • 2021-06-05
        相关资源
        最近更新 更多