首页 > 解决方案 > scala类成员导致错误“类'类'必须声明为抽象或实现成员'成员'”

问题描述

我正在尝试学习Scala ObjectClass。我来自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 帖子中的建议添加一个伴随对象并遵循他们的建议:

object Wallet {
  var privateKey: PrivateKey
  var publicKey: PublicKey
}

我收到一个错误:

只有类可以有已声明但未定义的成员

TL;博士

我想将Wallet Java代码转换为Scala代码,我该如何实现呢?


更新(澄清我原来的问题)

所以,答案并不反映我的实际问题(我的想法)。我将尝试澄清。

Scala 支持各种构造函数。

正如@Josh在这里提到的,你会发现主要的构造函数

class Person(name: String) {
    var personName: String = name
}

辅助构造函数将是(通过扩展@Jos​​h 的示例),例如:

def this() {
    this("Unknown Person Name")
    // additional code
}

这些构造函数在此处进行了详细讨论,值得一读。

我感兴趣的是这个。

由于我已经声明了一个成员privateKeyand publicKey,所以我希望在我的班级中声明更多成员。并非所有这些成员都会在类初始化时实例化,但会在应用程序执行期间稍后实例化。

下面将为我上面描述的内容提供更多背景信息。我将实例化Wallet, 并在稍后阶段调用wallet.generateKeys()

class Wallet {

  var publicKey: PublicKey
  var privateKey: PrivateKey
  var balance: Int = 0

  def generateKeys(): Unit = {
    val keyPair =  KeyPairGenerator.getInstance("SHA-256").generateKeyPair()
    privateKey = keyPair.getPrivate
    publicKey = keyPair.getPublic
  }

  def getBalance(): Int = {
    balance
  }
}

这将需要声明一个变量,但在运行时未实例化,直到需要它为止。

将如何在 Scala 代码中定义。

标签: javascalaclassfunctional-programmingmember

解决方案


这样做是可能的,但这是代码异味。假设有人创建了您的钱包实例。他们必须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).

推荐阅读