访问案例类的静态成员

发布于 2024-10-14 10:17:10 字数 1160 浏览 2 评论 0原文

我有一些代码

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

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

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

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? If 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 =>
  ...
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

铃予 2024-10-21 10:17:10

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

您尝试通过调用 Ax 来访问名为“A”的值。范围内恰好有这样一个值 - 编译器为您的案例类 A 生成了伴生对象。

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

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

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

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" }
轻许诺言 2024-10-21 10:17:10

从您描述的问题的少量来看,案例类似乎不适合您。
替代模式包括...

常量:

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 类(正确使用):

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
}

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
}
や三分注定 2024-10-21 10:17:10

暂时把设计问题放在一边。

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

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

返回到设计,在您的案例类定义中,您在 B 的构造函数主体中声明“名称”,但您可以通过使用“ name' 作为参数:

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

然后可以像这样匹配:

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文