访问案例类的静态成员

时间:2011-01-28 05:28:31

标签: scala

我有一些代码

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

为什么我不能在没有实例化A类的情况下访问静态变量x?如果我输入

A.x

我收到以下错误:

error: value x is not a member of object A

编辑:

我错过了提及剩下的代码。以下是我想要使用的示例:

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")
                ^

至于为什么使用case类,没有为此目的定义case类。在其他地方我有一些代码:

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

3 个答案:

答案 0 :(得分:5)

好吧,你不能调用“静态”变量x,因为在Scala中没有静态变量。您声明x是A类的常规成员,如果您有A类实例,则可以访问该成员。

通过调用A.x尝试执行的操作是访问名为“A”的值。在范围中恰好有这样的值 - 编译器为您的案例类A生成了伴随对象。

但是这个对象A没有成员“x”,因此编译器正确地抱怨它。

您可以通过执行以下操作将值x添加到对象A而不是类/类型A:

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

答案 1 :(得分:3)

从你描述的问题的少量,听起来像案件类不适合你。 替代模式包括......

常量:

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
}

案例对象:

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 :(得分:2)

暂时搁置设计问题。

如果需要解决方法,则可以将标识符绑定到匹配的案例类或案例对象,并使用绑定的标识符来访问匹配实体的成员。绑定标识符可用于匹配中的保护语句或为匹配提供的操作:

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类定义中,你在B的构造函数体中声明了'name',但是你可以通过将'name'作为参数来获得更多的可用性:

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

然后可以这样匹配:

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

最后很难说没有进一步的细节,但我怀疑在一对一的基础上将案例类映射到大量类似实体可能不是最佳选择,更好地使用案例对象或有限数量的实例案例类甚至元组。