2014-02-17 2 views
7

Я использую Scala 2.10.2, и есть два класса регистра, которые имеют одинаковые поля:Тип альясинга класс случай в Scala 2,10

case class Foo(id: String, name: String) 
case class Bar(id: String, name: String) 

Я хотел бы сделать что-то вроде этого:

case class Thing(id: String, name: String) 
type Foo = Thing 
type Bar = Thing 

компилируется, но когда я пытаюсь создать Foo, я получаю:

scala> Bar("a", "b") 
<console>:8: error: not found: value Bar 
       Bar("a", "b") 
      ^

ли тип сглаживания не работает остроумие х классов?

ответ

12

При создании класса case Scala автоматически создает для него объект-компаньон. В вашем коде вы определяете псевдоним для типа Thing, то есть только для класса Thing. У вашего объекта-компаньона Thing все еще есть только 1 имя и никаких псевдонимов.

Один из способов «исправить» это создать ссылку на объект компаньон (не псевдоним типа), как это:

scala> val Bar = Thing 
Bar: Thing.type = Thing 

scala> Bar("a", "b") 
res1: Thing = Thing(a,b) 

Другой способ «исправить» это было бы переименовать импортированный объект с import package.{Thing => Bar}.

+1

'Вэл Bar = Thing' это добавит псевдоним объекта вместо типа псевдонима –

+0

Спасибо, я знаю. Я сделаю это более ясным в этом вопросе –

+0

@AlekseyIzmailov Я все равно скажу «создать ссылку на объект-компаньон _ вместе с _ псевдонимом типа». –

4
case class Thing(id: String, name: String) 
type Foo = Thing 
type Bar = Thing 

если вы говорите new Bar("a","b") он будет работать

4

Тип псевдонимы только псевдоним типа, а не какой-либо спутник объекта, который может быть поставляя фабричные методы (писать ли вы, что фабричный метод самостоятельно или получить «бесплатно» из компилятора).

С другой стороны, при импорте актов на имена и при наличии нескольких объектов, связанных с данным именем, импорт этого имени приводит к каждому референту импортированного имени. Кроме того, вы можете переименовать при импорте, и вы можете сделать это многократно, так что ...

scala> object Stuff { case class Thing(id: String, name: String) } 
defined module Stuff 


scala> import Stuff.Thing 
import Stuff.Thing 

scala> import Stuff.{Thing => Foo} 
import Stuff.{Thing=>Foo} 

scala> import Stuff.{Thing => Bar} 
import Stuff.{Thing=>Bar} 


scala> val thing1 = Thing("fing", "fang") 
thing1: Stuff.Thing = Thing(fing,fang) 

scala> val foo1 = Foo("yes", "no") 
foo1: Stuff.Thing = Thing(yes,no) 

scala> val bar1 = Bar("true", "false") 
bar1: Stuff.Thing = Thing(true,false) 

Это не хорошо для рендеринга с помощью toString, хотя, как вы можете видеть.

0

Вы хотите, чтобы Foo и Bar были различимы (как в случае разных классов случаев) или нет? Если да, и вы просто хотите, чтобы избежать повторения списка полей, вы можете сделать это:

case class Foo(thing: Thing) 
case class Bar(thing: Thing) 

Но это, очевидно, сделать их немного менее удобно использовать в сопоставлении с образцом или доступа к полям. Доступ к полю можно улучшить немного:

trait ThingWrapper { 
    def thing: Thing 
    def id = thing.id 
    def name = thing.name 
} 

case class Foo(thing: Thing) extends ThingWrapper 
case class Bar(thing: Thing) extends ThingWrapper 
Смежные вопросы