gpt4 book ai didi

scala - "apply"在 Scala 的伴生对象(带有 Trait)中如何工作?

转载 作者:行者123 更新时间:2023-12-02 09:36:07 28 4
gpt4 key购买 nike

来源:Scala MEAP v10 中的函数式编程

在下面粘贴的代码中

sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]

object List {
def sum(ints: List[Int]): Int = ints match {
case Nil => 0
case Cons(x,xs) => x + sum(xs)
}
def product(ds: List[Double]): Double = ds match {
case Nil => 1.0
case Cons(0.0, _) => 0.0
case Cons(x,xs) => x * product(xs)
}
def apply[A](as: A*): List[A] = {

if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}
val example = Cons(1, Cons(2, Cons(3, Nil)))
}

Cons对象大概是通过apply()构造的,但是类型签名不同,scala最终如何组装Cons实例。

虽然没有取消应用,但下面的代码工作得很好,将列表分解为 Cons(head, tail)

object a{
val x = List(1,2,3,4,5) match {
case Cons(x, Cons(2, Cons(4, _))) => x
case Nil => 42
case Cons(x, Cons(y, Cons(3, Cons(4, _)))) => x + y
case Cons(h, t) => h + List.sum(t)
case _ => 101
}
}

最佳答案

一个Cons实例始终由 Cons 构造' 构造函数。您可以直接调用它:

val myList = new Cons(1, new Cons(2, Nil)) // list containing the elements 1 and 2

apply伴随对象上的方法是一个工厂方法,它允许您使用更好的语法构造一个列表:

val myList = List(1, 2) // expanded to List.apply(1, 2) by the compiler ; same result as above

它们没有理由需要具有相同的类型签名,因为它们不需要以相同的方式调用。

至于为什么可以使用模式匹配而不定义 unapply方法:那是因为你定义了 NilCons作为案例类/对象。案例类免费获得许多功能(由编译器生成),包括 unapply方法(例如 equalshashcodetoString )。


编辑:基于评论的一些精度:

Scala 中的构造函数:在 Scala 中,每个类都有一个默认构造函数,其参数自动用作类中的字段 - 因此默认构造函数不需要有自己的方法体。例如,以下 Scala 类:

class Foo1(bar: Int)
class Foo2(val bar: Int)

大致相当于以下 Java 类:

public class Foo1 {
public Foo1(int bar) {
this.bar = bar;
}
private int bar;
}

public class Foo2 {
public Foo2(int bar) {
this.bar = bar;
}
private int bar;
public int getBar() {
return bar;
}
}

多态性: NilCons两者都延伸List 。这意味着a Cons是一种List 。因此,如果您创建 Cons 的实例与 val myList = new Cons(1, Nil) , myListCons 类型的对象...但它也是:

  • 类型 List
  • 类型 AnyRef ,因为它是所有引用类型的根类。 Scala 中的所有类都扩展 AnyRef默认情况下,所以 List延伸AnyRef (因为它没有明确的 extends 子句)。
  • 类型 Any ,它是所有 Scala 类型的根。

以下代码使用您的List/Cons/Nil实现:

val myList = List(1, 2, 3)
// Cons(1,Cons(2,Cons(3,Nil))) => result of the toString method generated by the compiler because it's a case class
myList.getClass.getName
// Cons => this is the concrete type of myList
myList.isInstanceOf[Cons[_]]
// true => myList is a Cons
myList.isInstanceOf[Nil.type]
// false
myList.isInstanceOf[List[_]]
// true => but it's also a kind of List
val foo: List[Int] = myList
// => this is allowed
myList.isInstanceOf[AnyRef]
// true
myList.isInstanceOf[Any]
// true

val anotherList = List()
// Nil
anotherList.getClass.getName
// Nil$ => the name is mangled with a $ sign to differentiate the 'object Nil' in case you also declare a 'class Nil'
anotherList.isInstanceOf[List[_]]
// true

关于scala - "apply"在 Scala 的伴生对象(带有 Trait)中如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26061497/

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