为了账号安全,请及时绑定邮箱和手机立即绑定

scala类成员导致错误“类'类'必须声明为抽象或实现成员'成员'”

scala类成员导致错误“类'类'必须声明为抽象或实现成员'成员'”

繁星coding 2022-07-06 10:00:55
我正在尝试学习Scala Object和Class。我来自Java,它与 Scala 非常相似,但在语法上不一样。在Java中,我会创建一个类似的类:public class Wallet {    private PublicKey publicKey;    private PrivateKey privateKey;    private int balance = 0;    public Wallet() throws NoSuchAlgorithmException {        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");        KeyPair keyPair = keyPairGenerator.generateKeyPair();        privateKey = keyPair.getPrivate();        publicKey = keyPair.getPublic();    }    public int getBalance(){        return balance;    }}这定义了一个Wallet对象的模板,我可以在Java中将其实例化为:Wallet wallet = new Wallet();这还将在构造函数中创建一个PrivateKeyand并将其分配给相应的类成员。PublicKeyWallet我知道Scala使用了一种略有不同的方法,其中类只是可实例化对象的模板,而Objects 是Singleton持久存储信息的类型对象。另外,根据这篇文章,我发现 an在文件Object中经常用作伴随对象。Class使用上面的Wallet示例,我试图在Scala中重新创建它。这是我到目前为止所拥有的:class Wallet {  var publicKey: PublicKey  var privateKey: PrivateKey  var balance: Int = 0  def this() {    this    val keyPair =  KeyPairGenerator.getInstance("SHA-256").generateKeyPair()    privateKey = keyPair.getPrivate    publicKey = keyPair.getPublic  }  def getBalance(): Int = {    balance  }}问题:“钱包”类必须声明为抽象或在“com.simple.blockchain.Wallet”中实现抽象成员“publicKey:PublicKey”现在这让我很困惑。在Java中,将未实例化的对象声明为类成员通常会是一个问题,因此,如果我尝试按照之前的 SO 帖子中的建议添加一个Companion Object并遵循他们的建议:object Wallet {  var privateKey: PrivateKey  var publicKey: PublicKey}我收到一个错误:只有类可以有已声明但未定义的成员
查看完整描述

4 回答

?
婷婷同学_

TA贡献1844条经验 获得超8个赞

这样做是可能的,但这是代码异味。假设有人创建了您的钱包实例。他们必须generateKeys在您的课程真正可用之前打电话。如果他们忘记并尝试使用密钥,他们将收到运行时错误或无意义的行为。相反,将它们设置在主构造函数(如Josh 建议的那样)或工厂/应用方法(如Andy 建议的那样)中。


如果你还是想做

如果你真的想要一个已声明但未初始化的字段......你不能,确切地说,甚至在 Java 中也不能。在 Java 中,未初始化的字段被隐式初始化为默认值(null对于对象)。在 Scala 中,您可以通过为其分配下划线 ( _) 来获得此行为:


var publicKey: PublicKey = _

var privateKey: PrivateKey = _

这些将被初始化为空。不过,请不要这样做。

您的代码的其他问题

  1. 在 Scala 中,您应该更val喜欢var.

  2. 您的所有变量都是公开的。我猜你至少打算balance保密,因为你也有一个getBalance方法。

  3. 您的Person示例不遵循惯用风格,因为您可以将其写为class Person(var personName: String).


查看完整回答
反对 回复 2022-07-06
?
小唯快跑啊

TA贡献1863条经验 获得超2个赞

摆脱def this() { ... }. 在 scala 中,构造函数体只是类声明之后的代码行。像这样:


class Person(name: String) {

    private val id: String = name


    // ... other fields, methods, etc.

}


查看完整回答
反对 回复 2022-07-06
?
互换的青春

TA贡献1797条经验 获得超6个赞

如果您需要在创建对象时未初始化的值,最好将它们设为Option值:


class Wallet {

  private var publicKey: Option[PublicKey] = None

  private var privateKey: Option[PrivateKey] = None

  private var balance: Int = 0


  def generateKeys(): Unit = {

    val keyPair =  KeyPairGenerator.getInstance("SHA-256").generateKeyPair()

    privateKey = Some(keyPair.getPrivate)

    publicKey = Some(keyPair.getPublic)

  }


  def getBalance = balance

}

这比使用更安全,null因为类型系统和运行时会在您使用它时检查该值是否有效。


但其他答案是正确的,如果可能的话,最好推迟创建这个对象,直到密钥可用。


查看完整回答
反对 回复 2022-07-06
?
收到一只叮咚

TA贡献1821条经验 获得超4个赞

您可以在伴随对象上添加应用:


class Wallet private (val privateKey: PrivateKey, publicKey: PublicKey, balance: Int) {

  def getBalance(): Int = balance

}

object Wallet {

  def apply(): Wallet = {

    val keyPair =  KeyPairGenerator.getInstance("SHA-256").generateKeyPair()

    val privateKey = keyPair.getPrivate

    val privateKey = keyPair.getPublic

    new Wallet(privateKey, privateKey, 0)

  }

}


查看完整回答
反对 回复 2022-07-06
  • 4 回答
  • 0 关注
  • 89 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信