【问题标题】:Is type checking ever OK?类型检查可以吗?
【发布时间】:2009-01-15 18:43:40
【问题描述】:

即使您正在检查接口,类型检查是否也被视为不好的做法?我知道您应该始终对接口而不是实现进行编程 - 这就是它的意思吗?

比如在PHP中,下面这样可以吗?

if($class instanceof AnInterface) {
   // Do some code
}

或者有没有更好的方法来根据类类型改变代码的行为?

编辑:为了清楚起见,我说的是检查一个类是否实现一个接口,而不仅仅是它是某个类的实例。

【问题讨论】:

    标签: oop inheritance interface


    【解决方案1】:

    只要你关注LSP,我看不出问题。您的代码必须与接口的 any 实现一起使用。只要您可以正确使用接口的任何实现,某些实现会导致您遵循不同的代码路径,这不是问题。

    如果您的代码不适用于接口的所有实现,那么您一开始就不应该使用该接口。

    【讨论】:

    • 这是一个很好的观点,但是如果您进行类型检查,很容易让您陷入每次添加新子类时都必须更新方法的情况。应该避免这种情况以支持多态性。
    • 肯定只要子类实现了接口就不需要做任何改动?
    【解决方案2】:

    如果你可以避免类型检查,你应该这样做;但是,我发现它很方便的一个场景是,我们有一个 Web 服务,它接收一条消息,但消息的内容可能会改变。我们必须将消息持久化回 db,以便让正确的组件将消息分解到适当的表中,我们在某种意义上使用了类型检查。

    我发现比 if ($class instanceof SomeOtherType) 更常见和更灵活的是例如定义一个 IProcessing 策略,然后使用基于类型 $class 的工厂创建正确的类。

    所以在c#中大致是这样的:

    void Process(Message msg)
    {
        IProcessor processor=ProcessignFactory.GetProcessor(msg.GetType()); 
        processor.Process(msg); 
    }
    

    但是,如果您只处理一个不会更改的变体使用类型检查来实现它,并且当/如果您发现自己错了并且需要更多检查然后将其重构为更健壮的解决方案。

    【讨论】:

      【解决方案3】:

      在我的实践中,任何类型检查(以及类型转换)总是表明代码或语言有问题。

      所以我尽量避免它。

      【讨论】:

      • 如何在不进行类型转换的情况下有效地确定可枚举集合中的项目数?
      【解决方案4】:

      在接口提供了做某事所需的所有方法但没有提供足够的方法来做好某事的情况下,通常需要运行时类型检查。这种情况的一个主要示例是确定可枚举序列中的项目数。可以通过枚举序列来做出这样的确定,但是许多可枚举对象“知道”它们包含多少项。如果一个对象知道它包含多少项目,那么询问它可能比枚举集合并单独计算项目更有效。

      可以说,IEnumerable 应该提供一些方法来询问它对包含的项目数量的了解[认识到对象可能知道该数字是无限的,或者最多为 4,591(但可能是少得多)等],但事实并非如此。理想的情况是,如果可以生成一个新版本的IEnumerable 接口,其中包括它添加的任何“新”方法的默认实现,并且这种接口可以被认为是由当前版本的任何实现实现的。不幸的是,因为不存在这样的功能,所以在不枚举的情况下获取可枚举集合的计数的唯一方法是检查它是否实现了任何已知的包含Count 成员的集合接口。

      【讨论】:

      • 这只是 C# 扩展方法的一个问题,因为它们是静态解析的并且不是多态的。如果 C# 支持特征,类可以专门化 Count 实现,前提是它们可以提供更有效的实现。
      • @Lee:恕我直言,正确的方法是在 .NET 类加载器中添加代码,通过使 vtable 指向与接口 [结构的一个版本,类的一个版本],其签名作为第一个参数包括对实现类型的引用或 byref。这会为类加载过程增加少量时间,但它会允许像IList<T> 这样的接口包含对某些但不是所有实现有用的方法,而无需强制...
      • ...IList<T> 的所有实现都包含未使用方法的样板存根。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-20
      • 2021-08-29
      • 2013-03-14
      • 2011-06-29
      • 2016-11-13
      • 2013-05-18
      相关资源
      最近更新 更多