简体   繁体   中英

Scala type A = B with C, what does `with` mean

Could someone explain and provide real world examples of using with keyword in defining types?

Let's define type

type T = A with B

What does it mean? When should it be used? How to instantiate type T ?

I guess it's called type conjunction.

You can use it to enforce that a certain type must extend all of the specified traits / classes. A stupid example:

scala> trait Quackable {
     |   def quack = println("quack")
     | }
defined trait Quackable

scala> trait Walkable {
     |   def walk = println("walk")
     | }
defined trait Walkable

scala> case class Duck(name: String) extends Quackable with Walkable
defined class Duck

scala> def foo(d: Quackable with Walkable): Unit = {
     |   d.quack
     |   d.walk
     | }
foo: (d: Quackable with Walkable)Unit

scala> foo(Duck(""))
quack
walk

// Or you can create a type alias and use it.    
scala> type QW = Quackable with Walkable
defined type alias QW

scala> def foo(d: QW): Unit = {
     |   d.quack
     |   d.walk
     | }
foo: (d: QW)Unit

scala> foo(Duck(""))
quack
walk

// If you need to retain the type information for some reason, you can use a type parameter.

scala> def foo[A <: Quackable with Walkable](d: A): A = {
     |   d.quack
     |   d.walk
     |   d
     | }
foo: [A <: Quackable with Walkable](d: A)A

scala> foo(Duck(""))
quack
walk
res1: Duck = Duck()

As for "how to instantiate it": don't think of it that way. type creates type aliases / synonyms / functions, which do not necessarily represent concrete instantiable types.

Edit:

If you're familiar with Java, with as used above is similar to Java's & .

public static <QW extends Quackable & Walkable> void foo(QW d) {
  d.quack();
  d.walk();
}

However unlike Java's & , with gives you a proper type. The first definition of foo I wrote cannot be translated to Java. Also you cannot do the following with Java's & .

scala> case object Quackawalkasaurus extends Quackable with Walkable
defined module Quackawalkasaurus

scala> List(Duck(""), Quackawalkasaurus)
res2: List[Product with Serializable with Quackable with Walkable] = List(Duck(), Quackawalkasaurus)

// Add an explicit type annotation if you want to remove unwanted common super-traits/classes.
scala> List(Duck(""), Quackawalkasaurus) : List[Quackable with Walkable]
res3: List[Quackable with Walkable] = List(Duck(), Quackawalkasaurus)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM