子类型优于类型类的优点 [英] Advantages of subtyping over typeclasses

查看:114
本文介绍了子类型优于类型类的优点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

与类型类相比, OOP 子类型的优点是什么?换句话说,现在我们有了类型类,是否有理由继续使用 OOP 子类型?



PS:我是Scala程序员。

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

  class MyEvent extends Event {
val name =foo
}



 类MyEvent {
VAL名称= foo 的
}

对象MyEvent2Event {
隐式DEF转换(myEvent:MyEvent)=新事件{VAL名称= myEvent.name}
}

第二种形式允许更多的灵活性-hoc多态性,命名的自由度以及一般的不良状态,但是输入这五十种转换方法,然后在需要类型类时进行适当的导入将会成为一种正确的痛苦。如果你不需要灵活性,很难看到收益。另外,第二个关键词是唠叨的新,这会产生无穷无尽的这是过度压缩垃圾收集器的争论。

对于引入可变状态的mixin继承,情况更糟糕。请考虑以下的性状,从生产代码采取:

 性状锁定{
私人VAL锁=新的ReentrantReadWriteLock()

DEF withReadLock [T](体:=> T):T = {
尝试{
lock.readLock.lock()
主体
} finally {
lock.readLock.unlock()
}
}
//与withWriteLock相同
}

由于存在lockval,所以非常方便地使用mixin继承,并且不能真正适用于Scala类型类。它应该去哪里?如果你把它放在适应类中,你就失去了大部分特征的封装值。如果将它放入适配器代码中,则锁不再能够保护任何内容,因为每次调整时都会锁定不同的锁对象。

What are the advantages of OOP subtyping over typeclasses, if any? In other words, now that we have typeclasses, is there any reason to still use OOP subtyping?

PS: I am a Scala programmer.

解决方案

At present, the syntactic overhead of Scala type classes is a good bit larger than for subtyping via trait inheritance, as is the potential runtime overhead. Imagine a case where you need to have fifty different types of events conform to an interface to support an event processing engine. Much easier to write

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

than

class MyEvent{
   val name = "foo"
}

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

The second form allows a lot more flexibility in terms of post-hoc polymorphism, freedom of naming, and general bad-assery, but typing out those fifty conversion methods and then doing the appropriate imports when the typeclass is needed is going to get to be a right pain. If you don't need the flexibility, it's tough to see the payoff. Plus there's that nagging "new" keyword in the second, which will spawn endless "is this overstressing the garbage-collector" arguments.

The situation is worse for mixin inheritance that introduces mutable state. Consider the following trait, taken from production code:

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
}

Incredibly handy use of mixin inheritance, and not really doable with Scala type classes, due to the presence of the "lock" val. Where should it go? If you put it in the adapted class, you lose most of the encapsulation value of the trait. If you put it in the adapter code, the locks no longer protect anything, since you'd be locking on different lock objects every time you're adapted.

这篇关于子类型优于类型类的优点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆