我希望通过在基本抽象类中放置apply / unapply方法来在我的项目中保存大量代码。是不是可以在case类中编写apply方法,而是在抽象类中编写?
我在下面编写的代码实际上不起作用,但我相信它描述了我想要完成的任务。 Animal类中的apply方法不是将要编译的有效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")
答案 0 :(得分:2)
首先,您希望apply
方法位于随播对象上,而不是类本身,这样您就可以调用Rabbit(...)
,因为这是Rabbit.apply
的糖。根据您拥有的内容,修复错误的this(...)
调用,您需要Animal
的实例才能调用apply方法。
其次,你似乎混淆了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
将失败。
输入case class
es。 Scala编译器会将某些辅助方法插入到类本身中,并在遇到一个时将它作为伴侣。令人惊讶的是,Big Two是apply
,它创建了具有语法Foo(...)
的对象及其邪恶的双unapply
,它分解了对象以进行模式匹配。编译器只为主构造函数生成apply
方法,并且它具有完全相同的签名。
所以看起来我们不能只使用构造函数做任何事情,所以让我们继续以某种方式自动将apply
方法放入伴随对象中。一种方法是使用宏,但这对此来说太复杂了。另一种方式,我们定义一个混合到伴随对象的特征需要反射并且也会很复杂,并且每个类需要两行,一行用于class
,一行用于{{1 }}。那么现在呢?
输入默认参数!事实上,这实际上是默认参数的教科书案例。 (抱歉在丛林周围殴打。)定义基类object
:
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)
设置为age
,默认2
为{{1} }}
TL; DR 默认参数