Доступ к статическим членам case-классов - PullRequest
0 голосов
/ 28 января 2011

У меня есть код

case class A(s:String) {val x = "hello"}

Почему я не могу получить доступ к статической переменной x без создания экземпляра класса A?Если я наберу

A.x

, я получу следующую ошибку:

error: value x is not a member of object A

Edit:

Я пропустил упоминание оставшегося кода.Вот пример, который я хотел бы использовать:

abstract class A { val name:String }
case class B(i:Int) extends A { val name = "B" }
case class C(b:Boolean) extends A { val name = "C" }
def getType(s:String) = s match {
  case B.name => println ("Object B")
  case C.name => println ("Object C")
}

Ошибка:

  scala> def getType(s:String) = s match {
 |       case B.name => println ("Object B")
 |       case C.name => println ("Object C")
 |     }
 <console>:11: error: value name is not a member of object B
         case B.name => println ("Object B")
                ^
 <console>:12: error: value name is not a member of object C
         case C.name => println ("Object C")
                ^

Что касается использования классов прецедентов, классы прецедентов для этой цели не определены.В другом месте у меня есть код вроде:

def func(a:A) = a match {
  case b:B =>
  case c:C =>
  ...
}

Ответы [ 3 ]

5 голосов
/ 29 января 2011

Ну, вы не можете вызвать «статическую» переменную x, потому что в Scala нет статических переменных. Вы объявляете x регулярным членом класса A, к которому вы могли бы получить доступ, если бы у вас был экземпляр класса A.

То, что вы пытаетесь сделать, вызывая A.x, - это доступ к значению с именем «A». В области видимости есть такое значение - компилятор сгенерировал сопутствующий объект для вашего класса дел A.

Но этот объект A не имеет члена "x", поэтому компилятор справедливо жалуется на это.

Вы можете добавить значение x к объекту A вместо класса / типа A, выполнив следующие действия:

case class A(s:String)
object A { val x = "hello" }
3 голосов
/ 28 января 2011

Из небольшого количества описанной вами проблемы кажется, что классы кейсов просто не для вас.Альтернативные шаблоны включают ...

Константы:

val Abs1 = "1" //note that it starts with an uppercase letter
val s: String = ...
s match {
  case Abs1 => ...
  case _ =>
}

Экстракторы:

object Positive {
  def unapply(i: Int): Option[Int] = if(i >= 0) Some(i) else None
}

val i: Int = ...
i match {
  case Positive(p) => ... //p will be bound to the matched positive number
  case _ => ...
}

Классы дел (используются правильно):

case class MyType(s: String)
val x: MyType = ...

x match {
  case MyType("a") => ...
  case MyType("b") => ...
  case MyType(matched) => ...
    //matched will be bound to whatever string was used to construct the MyType instance
}

Объекты Case:

abstract sealed trait Foo { def s: String }
case object Bar extends Foo { val s = "I'm a Bar" }
case object Baz extends Foo { val s = "I'm a Baz" }

val x: Foo = ...
x match {
  case Bar => ...
  case Baz => ...
  //no other possibilities because Foo is sealed
}
2 голосов
/ 28 января 2011

Оставляя на минуту вопросы дизайна.

Если вам нужен обходной путь, вы можете привязать идентификатор к сопоставленному классу case или объекту case и использовать связанный идентификатор для доступа к членам совпадающей сущности. Связанный идентификатор можно использовать в защитных инструкциях в матче или в действии, предусмотренном для матча:

case class Bob(x: String, y: String) {val z = "Bragging"}

val bob1 = Bob("Big", "Bad")

bob1 match {
  case b @ Bob(x, y) if b.z == "Bragging" => println("Got "+x+", "+y+", "+b.z+" Bob!")
  case _ =>
}

case object Bob {val z = "Balding"}

val bob2 = Bob

bob2 match {
  case b @ Bob if b.z == "Balding" => println("Got "+b.z+" Bob!")
  case _ =>
}

Возвращаясь к дизайну, в своем определении класса case вы объявляете 'name' в теле конструктора B, но вы получите больше возможностей от использования 'name' в качестве параметра:

case class B(i: Int, name: String) extends A

Что может тогда соответствовать так:

def getType(s:String) = s match {
  case B(_, name) => println ("Object B("+name+")")
  ...

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...