【问题标题】:Casting between subclass/interface and superclass子类/接口和超类之间的转换
【发布时间】:2012-07-04 14:04:00
【问题描述】:

考虑以下代码:

interface IFace {}

abstract class Supertype {}

class Subtype1 extends Supertype implements IFace {}
class Subtype2 extends Supertype implements IFace {}
class Subtype3 extends Supertype {}

class Foo {
    //Contains elements of Subtype1 and Subtype2
    List<IFace>     ifaceList = new ArrayList<IFace>();

    //Contains elements of Subtype1, Subtype2, and Subtype3
    List<Supertype> superList = new ArrayList<Supertype>();   

    void CopyItem() {
        superList.add( (Supertype) ifaceList.someElement() );
    }
}

如果我知道只有子类型会实现IFace,那么将IFace 元素转换为Supertype 是否安全?是否有可能确保只有子类型会实现IFace

我正在尝试使用IFace 作为标记接口,以仅在第一个列表中保留某些子类型,并在第二个列表中允许任何子类型。

【问题讨论】:

    标签: java class interface casting


    【解决方案1】:

    如果我知道只有子类型会实现 IFace,那么将 IFace 元素强制转换为超类型是否安全?

    是的。

    是否有可能确保这一点?

    如果您的意思是“是否有可能确保只有Supertype 的子类实现IFace” - 否。接口可以由任何东西实现。

    如果您的意思是“是否有可能确保转换成功” - 是的,您可以在转换前使用instanceof

    【讨论】:

    • 实例? .....(我理解你的观点,但我想你也明白我的意思)。
    • @assylias:不确定你的意思。你可以确保演员阵容是安全的,但据我所知,这不是 OP 想要确保的。
    • 这就是我的意思。不确定是否是/不是问题。
    • 考虑IFace一个标记接口,以确保只有某些子类型在第一个列表中,但任何子类型都可以在第二个列表中。有没有更好的办法?
    • @BrianTempleton:啊,我明白了——虽然IFace 的所有实现都是Supertype 子类,但并非所有子类都实现IFace。我已经删除了答案的最后一部分。
    【解决方案2】:

    最安全的方法是让 Supertype 实现 IFace。如果这不可能,那么只要实现 IFace 的 每个类 也是 Supertype 子类,就可以安全地将 IFace 元素转换为 Supertype。您必须确保暂时是正确的,这很容易出错。

    【讨论】:

      【解决方案3】:

      如果我知道只有子类型会实现 IFace,那么将 IFace 元素强制转换为超类型是否安全?

      如果您确定所有 IFace 元素也扩展了 Supertype,那么这不是问题。但在未来,这可能不再是真的。

      是否有可能确保这一点?

      是的。您可以尝试在 ClassCastException 上捕获,甚至在使用运算符 instanceof 进行强制转换之前更好地对其进行测试

      void CopyItem() {
          IFace obj = ifaceList.someElement();
          if (obj instanceof Supertype) superList.add( (Supertype)obj );
          else System.err.println("WARNING: IFace object is not a Supertype.");
      }
      

      【讨论】:

        【解决方案4】:

        如果我只知道将 IFace 元素转换为 Supertype 是否安全 子类型会实现 IFace 吗?

        如果你知道你的代码,并且每个实现IFace 的类也是Supertype 的子类,那没有问题,但你总是可以使用instanceof 运算符检查Supertype,以确保.

        是否有可能确保这一点?

        考虑对您的代码进行以下修改:

        interface IFace {}
        
        abstract class Supertype {}
        
        abstract class SupertypeAndFace extends Supertype implements IFace {}
        
        class Subtype1 extends SupertypeAndFace {}
        class Subtype2 extends SupertypeAndFace {}
        class Subtype3 extends Supertype {}
        
        class Foo {
            //Contains elements of Subtype1 and Subtype2
            List<SupertypeAndFace> ifaceList = new ArrayList<SupertypeAndFace>();
        
            //Contains elements of Subtype1, Subtype2, and Subtype3
            List<Supertype>        superList = new ArrayList<Supertype>();   
        
            void CopyItem() {
                superList.add(ifaceList.someElement());
            }
        }
        

        在那里,不需要强制转换,因为您确保SupertypeAndFace 的每个实例都扩展Supertype 并实现IFace

        毕竟,如果SupertypeIFace 如此相关以至于您知道所有(或至少大部分)实现IFace 的类也是Supertype 的子类,那么您可能需要新的抽象.

        但是,如果您还希望 ifaceList 包含实现 IFace 但不是 Supertype 的子类型的其他元素,则此解决方案无效。如果是这种情况,您可以使用 instanceof 运算符来检查演员表的安全性,如其他答案所述。

        void CopyItem() {
            if (ifaceList.someElement() instanceof Supertype) {
                superList.add( (Supertype) ifaceList.someElement() );
            } else {
                // Throw exception if necessary
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2013-12-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-27
          • 2012-05-24
          • 2015-03-12
          • 2012-02-17
          • 1970-01-01
          相关资源
          最近更新 更多