Как я могу расширить тип для черты в Scala - PullRequest
2 голосов
/ 15 марта 2012

У меня есть тип, который я использую, который использует для ducktyping:

type t={
   def x:Int
 ...
}
class t2 {
 def x:Int=1
}
def myt:t=new t2 //ducktyping

Я хочу написать признак, который вынужден взаимодействовать с типом, но это НЕ работает:

trait c extends t { //interface DOES NOT COMPILE
  def x:Int=1
}

С другой стороны: если я пишу черту t1 вместо типа t, тогда я теряю функцию ducktyping:

trait t1 {
 def x:Int
}
type t=t1
trait c extends t1 { // t1 can be used as interface
  def x:Int=1
}
def myt:t=new t2  // DOES NOT COMPILE since t1 is expected

Так как же я могу использовать как ducktyping, так и интерфейс?

1 Ответ

4 голосов
/ 15 марта 2012

Вы можете расширять классоподобные сущности в Scala (т. Е. Классы, признаки, интерфейсы Java), а не типы в целом (т. Е. Структурные типы, параметры типа или члены).Тем не менее, вы можете самостоятельно набрать для всех этих.Это означает, что мы можем переписать ваш некомпилируемый trait c следующим образом:

trait c { self : t =>
  def x : Int = 1
}

В теле c тип this теперь известен как t, т.е.известно, что он соответствует структурному типу { def x : Int }, и будет возможно только смешать c в класс, который фактически соответствует этому структурному типу (либо путем непосредственного внедрения сигнатуры, либо, если он абстрагируется, путем повторного подтверждениявведите и распространяете обязательство на возможный конкретный класс),

type t = { def x : Int }

trait c { self : t => }

class t2 extends c {  // OK, t2 conforms to t
  def x : Int = 1
}

def myt : t = new t2  // OK, as before

class t3 extends c {  // Error: t3 doesn't conform to c's self-type
  def y : String = "foo"
}
...