开发者

Accessing static members of case classes

I have some code

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

Why can't I access the static variable x without instantiating the class A? I开发者_StackOverflowf I type

A.x

I get the following error:

error: value x is not a member of object A

Edit:

I missed out mentioning the remaining code. Here is the example that I would like to use:

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

The error:

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

As to why use case classes, the case classes are not defined for this purpose. Elsewhere I have some code like:

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


Well, you cannot call the "static" variable x, because in Scala there are no static variables. You are declaring x to be a regular member of class A, which you could access if you had an instance of class A.

What you try to do by calling A.x is accessing a value with the name "A". There happens to be such a value in scope - the compiler generated companion object for your case class A.

But this object A has no member "x", therefore the compiler rightly complains about it.

You can add the value x to the object A instead of the class/type A by doing the following:

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


From the small amount you described of the problem, it sounds like case classes are just not for you. Alternate patterns include...

Constants:

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

Extractors:

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 Classes (used properly):

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 Objects:

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
}


Leaving aside issues of design for a moment.

If you need a workaround then you can bind an identifier to a matched case class or case object and use the bound identifier to access members of the matched entity. The bound identifier can be used in guard statements in the match or in the action provided for the match:

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 _ =>
}

Returning to design, in your case class definition you declare 'name' in the constructor body of B but you would get more useability from having 'name' as a parameter:

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

Which could then match like this:

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

Finally it's hard to say without further detail but I suspect that mapping case classes to a large set of similar entities on a one to one basis is perhaps not the best choice, better to use case objects, or instances of a limited number of case classes or even tuples.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜