对类型组进行子类型化的优点

时间:2010-10-03 03:45:58

标签: oop scala programming-languages haskell functional-programming

如果有的话, OOP 子类型对类型类有什么好处?换句话说,既然我们有类型类,有没有理由继续使用 OOP 子类型?

PS:我是Scala程序员。

6 个答案:

答案 0 :(得分:14)

目前,Scala类型类的语法开销比通过trait继承进行子类型更大,因为潜在的运行时开销也是如此。想象一下,您需要有50种不同类型的事件符合支持事件处理引擎的接口。写起来容易得多

class MyEvent extends Event{
  val name = "foo"
}

class MyEvent{
   val name = "foo"
}

object MyEvent2Event{
   implicit def convert(myEvent:MyEvent) = new Event{ val name = myEvent.name}
}

第二种形式允许在事后多态性,命名自由和一般错误的方面提供更大的灵活性,但输入那五十种转换方法,然后在需要类型类时进行适当的导入将是变得正确的痛苦。如果你不需要灵活性,很难看到收益。另外,在第二个关键字中唠叨“新”关键字,这将产生无穷无尽的“这是对垃圾收集器的过度压力”的论点。

引入可变状态的mixin继承的情况更糟。考虑以下特征,取自生产代码:

trait Locking{
   private val lock = new ReentrantReadWriteLock()

   def withReadLock[T](body: => T):T={
      try{
         lock.readLock.lock()
         body
      }finally{
         lock.readLock.unlock()
      }
   }
   // same for withWriteLock
}

由于存在“锁定”val,令人难以置信的方便使用mixin继承,而不是真的可以使用Scala类型类。它应该去哪里?如果将它放在改编的类中,则会丢失该特征的大部分封装值。如果将它放在适配器代码中,则锁不再保护任何东西,因为每次调整时都会锁定不同的锁定对象。

答案 1 :(得分:9)

就个人而言,我发现OOP在处理得好的约束下更容易处理。换句话说:在你实际上不需要类型类的情况下,我发现对象更容易理解。

但是,这可能仅仅是对象的典型类型嵌入所具有的语法开销的工件。如果Haskell对于一些常见类型的类型模式具有语法糖,那么这种差异可能会消失。

我发现更有趣的是,Haskell社区显示类型类比对象更强大,因为在类型类中存在对象的简单嵌入,但是类型对象不能做对象。然而,Scala社区显示对象至少与类型类 1 一样强大,因为在对象中存在一个简单的类型嵌入。

这似乎表明两者之间的关系比通常认为的更为亲密。


1 见Bruno C.d.S的Type Classes as Objects and Implicits。 Oliveira,Adriaan Moors和Martin Odersky,以及the discussion of that paper on Lambda the Ultimate,特别是Paul Snively的这个很好的总结(重点补充):

  

Martin Odersky和团队关于如何使用统一的OO和FP语言进行类型分类的设计决策继续带来令人着迷的成果。 暗示看起来越来越不像“穷人的类型”,并且越来越像是对类型类的改进,在我看来快速阅读本文。

答案 2 :(得分:6)

在一种非纯粹功能的语言中,子类型可以让你有相同用法的不同副作用;使用类型类并不总是很容易实现。 (当然,你可以实现它;它对我来说似乎更尴尬。)

此外,子类型可以更有效 - 它是一种缓存“X是Y”的信息的方法,无需重复转换(或编译器英雄来缓存该信息)X到Y.对于非常深层次的,这个可能是一个问题。

答案 3 :(得分:3)

答案 4 :(得分:3)

至少Scala的另一个区别是,子类链只是起作用,而类型链很多。如果我们有类型A,B和C,那么如果A< B和B<那么C必然是A< C.但是,如果A<%B和B<%C,则不一定是A<%C的情况。这是因为Scala编译器不会应用多个隐式转换,否则类型推断因为困难和(IIRC)可能不可判定。

答案 5 :(得分:2)

继续支持OOP的一个实用理由是互操作性。 BitC讨论中目前正在进行的一个问题是,是否要为该语言添加单继承。有实用的利弊,并且对正式类型系统和类型推断的影响也有问题。&/ p>

有一段时间,类型类的实例解析机制让我们确信类型类因缺乏链接安全性而存在根本缺陷。在没有词法范围的解析机制的情况下,类型类实例解析无法按人类术语进行扩展:一个开发组的更改可能会导致由另一个地方由完全不同的组编写的应用程序中的链接错误。这让我们不情愿地看着单个继承和某种形式的F < + SelfType排序方案。当实例具有不同专业化程度的多个分辨率时,存在相关问题。

我们已经开始采用实例解决方法来解决这个问题,让我们感到满意。我们现在正在努力解决的问题是(a) BitC 程序是否需要进行子类型化,如果是这样的话,以及(b)即使我们不这样做,是否仍然可以与OO语言中的程序进行互操作要求我们支持可表达继承的类型系统,并因此支持可以使用它的语言。

这些都不是OP问题的任何结论性答案。我想,重点是这里的问题超出了任何特定语言的设计范围。还需要考虑人为因素和互操作性问题。

Jonathan Shapiro