gpt4 book ai didi

scala - (Scala) 如何从抽象类扩展应用方法?

转载 作者:行者123 更新时间:2023-12-01 09:04:41 25 4
gpt4 key购买 nike

我希望通过将 apply/unapply 方法放在基本抽象类中来在我的项目中节省大量代码行。 apply方法可以不写在case类中,而是写在抽象类中吗?

我在下面编写的代码实际上不会起作用,但我相信它描述了我想要完成的事情。 Animal 类中的应用方法不是将编译的有效 scala。

abstract class Animal(name:String,color:String,age:Int) {
def apply(name:String, color:String, age:Int) = this(name,color,string)
def apply(name:String, color:String) = this(name,color,0)
def apply(name:String) = this(name,"",0)
}

case class Rabbit(n:String,c:String,a:Int) extends Animal(n,c,a)
case class Squirrel(n:String,c:String,a:Int) extends Animal(n,c,a)
case class Dog(n:String,c:String,a:Int) extends Animal(n,c,a)
case class Cat(n:String,c:String,a:Int) extends Animal(n,c,a)

//(Ran elsewhere)
Rabbit("Billy")
Dog("Charlie","Brown",5)
Cat("Sprinkles","White")

最佳答案

首先,您希望您的 apply 方法在伴随对象上,而不是在类本身上,这样您就可以调用 Rabbit(...) ,因为这是 Rabbit.apply 的糖。有了你所拥有的,修复不正确的 this(...) 调用,你需要一个 Animal 的实例来调用应用方法。

其次,您似乎将 apply 和构造函数混在一起了。在 Scala 中,当您定义一个类时,名称旁边的参数定义了主构造函数。然后类的主体包含主构造函数的主体。您可以定义辅助构造函数,它们看起来就像方法定义,只是它们不返回任何内容并且被命名为this。这是一个辅助构造函数:

def this(qux: Qux) = {
// Must call another constructor (super(...), this(...))
this(qux.foobar)
this.foo = qux.bar
}

只能使用new 关键字调用构造函数(从另一个构造函数外部)。 没有其他方法可以调用构造函数。(除非,呃,你调用了一个调用构造函数(或反射 (ew))的方法。)当你执行 Foo(5),您不是直接调用构造函数,而是在伴随对象上调用 Foo.apply(5)。对于普通类 Bar,执行 Bar(...) 将失败,除非伴随对象定义了 apply 方法。

输入案例类es。 Scala 编译器会在遇到类时将某些辅助方法插入到类本身和它的同伴中。令人惊讶的两大巨头是 apply,它使用 Foo(...) 语法创建对象,而它的邪恶双胞胎 unapply,它分解对象以进行模式匹配。编译器只为主构造函数生成一个 apply 方法,并且它具有完全相同的签名。

所以看起来我们不能只用构造函数做任何事情,所以让我们继续以某种方式自动将 apply 方法放入伴随对象中。一种方法是使用宏,但这太复杂了。另一种方式,我们定义一个你混合到伴随对象中的特征将需要反射并且也会很复杂,并且每个类需要两行,一个用于 class,一个用于对象。那么现在呢?

输入默认参数!事实上,这实际上是默认参数的教科书案例。 (抱歉拐弯抹角。)定义基类 Animal:

abstract class Animal(name: String, color: String, age: Int)

现在,对于每个派生类,在构造函数中使用默认参数。默认参数的形式为 $arg: $type = $default,或者基本上是一个带有“等于某物”的普通参数。这里的默认值似乎是 color = ""age = 0

case class Rabbit(name: String, color: String = "", age: Int = 0) extends Animal(name, color, age)

现在,表达式 new Rabbit("Fooey", "white") 将被翻译成 new Rabbit("Fooey", "white", 0)。 (不是真的,但足够接近。) apply 方法也是如此。但是请注意,这并没有准确定义您的“示例”的功能。定义 age 而不定义 color 是可能的,像这样: Rabbit("Pit", age = 2) sets age2,默认 color""

TL;DR 默认参数

关于scala - (Scala) 如何从抽象类扩展应用方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38341759/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com