列表(对象)类型的表达式不符合预期的列表scala



据说我有以下内容

case class test {
a:string
b: string
c: Int
d: Int }

var temp = List(test("lol","lel",1,2))
var total = List(test)
total = total:::temp //this doesn't work because temp is of type [test] while total is of type [test.type]

我不明白其中的区别。 我想使用它的原因是我想有一个运行列表,其中元素将被有条件地添加到循环中。 因此,在这种情况下,total最初应该是一个空列表,其中包含test对象。我该怎么做?

任何反馈不胜感激!

让我先解释一下关于 Scala 的一些基础知识。

在 Scala 中,你定义了一个类,如下所示,

scala> class Demo(a: String, b: Int) {
|   def stringify: String = a + " :: " + b
| }
// defined class Demo

您可以将class视为提供给 Scala 的蓝图,该蓝图将用于创建该class的实例。在这里,class Demo的每个实例都将有两个属性 -a将是一个Stringb将是一个Int和一个方法 -stringify将返回一个String

scala> val demo1 = new Demo("demo1", 1)
// demo1: Demo = Demo@21eee94f
scala> demo1.getClass
// res0: Class[_ <: Demo] = class Demo

这里demo1classDemo的一个实例,并且具有typeDemo

Scala还有一个object的概念,它们是专门生成的内部类的实例。

scala> object OtherDemo {
| val a: Int = 10
| }
// defined object OtherDemo
scala> DemoObject.getClass
// res2: Class[_ <: OtherDemo.type] = class OtherDemo$

在这里,OtherDemo将是该特殊生成的classOtherDemo$的唯一实例,并且具有typeOtherDemo.type.

然后是斯卡拉的case class

scala> case class AnotherDemo(a: Int)
// defined class AnotherDemo

这不仅会创建一个classAnotherDemo,还会创建一个我们称之为伴随对象的objectAnotherDemo。这相当于,

class AnotherDemo(a: Int)
object AnotherDemo {
def apply(a: Int): AnotherDemo = new AnotherDemo(a)
def unapply(anotherDemo: AnotherDemo): Option[Int] = Some(anotherDemo.a)
// And many more utility functions
}

我们称这种objectAnotherDemoclassAnotherDemocompanion object

我们可以通过两种方式创建AnotherDemo实例,

// By using new keyword, as we can do for any class
scala> val anotherDemo1 = new AnotherDemo(1)
// anotherDemo1: AnotherDemo = AnotherDemo(1)
// Or we can use `apply` method provided by companion object
scala> val anotherDemo2 = AnotherDemo(2)
// anotherDemo2: AnotherDemo = AnotherDemo(2)
scala> anotherDemo1.getClass
// res6: Class[_ <: AnotherDemo] = class AnotherDemo
scala> anotherDemo2.getClass
// res7: Class[_ <: AnotherDemo] = class AnotherDemo
scala> AnotherDemo.getClass
// res8: Class[_ <: AnotherDemo.type] = class AnotherDemo$

此外,在 Scala 中,您的类名应该以大写字母开头。这使您能够轻松地将它们与应以小写字母开头的实例变量区分开来。这有助于您避免混淆。

现在,它应该是a: String而不是a: string.

scala> case class Test(
|       a: String,
|       b: String,
|       c: Int,
|       d: Int
|     )
// defined class Test

现在,当你写作时,

scala> var temp = List(Test("lol","lel",1,2))
// temp: List[Test] = List(Test(lol,lel,1,2))

它实际上相当于,

var temp = List.apply(Test.apply("lol","lel",1,2))

val test1 = Test.apply("lol","lel",1,2)
var temp = List.apply(test1)

Test.applyTest不是你的class Test而是companion object Test。调用Test.apply会返回一个class Test实例,该实例正在传递给List.apply,以最终获得包含此Test实例的typeList[Test]List

但是当你写这篇文章时,

scala> var total = List(Test)
// total: List[Test.type] = List(Test)

您正在创建类型为List[Test.type]List,其中包含该companion objectTest

专注于total: List[Test.type]部分......这意味着totaltypeList[Test.type]variable,这意味着它将想要指向typeList[Test.type]value/instance,并且会拒绝指向其他任何东西。

现在。。。你正在尝试这样做,

total = total ::: temp

这相当于,

val x = total ::: temp
total = x

这实际上是,

val x = temp.:::(total)
total = x

现在看看这个val x = total ::: temp

scala> val x = total ::: temp
// x: List[Serializable] = List(Test, Test(lol,lel,1,2))

你看。。。此x属于List[Serializable]类型。所以当你尝试total = x时,你会得到以下错误,

scala> total = x
// <console>:13: error: type mismatch;
// found   : List[Serializable]
// required: List[Test.type]
//       total = x
//               ^

这意味着total需要List[Test.type]但您正在给它一个List[Serializable]

您正在寻找total = List.empty[test]而不是List(test)。 前者创建一个List[test]类型的空列表,后者是List[test.type]类型的单元素列表(test.typetest不同 - 它是它自己的对象,表示test实例的类型)。

另外,不要使用var.它们是邪恶的,在 99% 的用例中并不是真正需要的。只要假装关键字根本不存在,直到你对语言有足够的把握,能够自信地区分其他1%。

当你这样做时:

var total = List(test)

您没有初始化对象测试,这就是为什么列表的类型是 Test.type,您只是为对象创建模板列表。

改为执行此操作时:var temp = List(test("lol","lel",1,2))

Yo 从模板(类,在本例中为 Test)实例化对象,因此 temp 的类型为List[Temp]

因此,如果您执行以下操作:

val template = Test那么 t 的类型是Test.type

你可以像这样从template实例化一个对象 Test:

val instantiated = template("lol","lel",1,2)

正如您在示例中所看到的,total变量只是一个模板列表,您可以从中实例化对象,而temp变量是 Test 类型的对象列表。

要创建 Test 类型的对象的空列表,您只需执行以下操作:

val t: List[Test] = List.empty

然后,您可以将任何对象(类型为Test)添加到此列表中

根据您的描述("我想要一个运行列表,其中元素将被有条件地添加到循环中"),我的理解是,您正在从某个来源获取Test对象并希望将它们放入列表中,但前提是它们满足某些条件。我们可以将此要求表示为一种方法。为方便起见,我们将该方法放在Test伴随对象中。伴随对象是放置应该可用的内容而无需实例化任何对象的地方。

case class Test(a: String, b: String, c: Int, d: Int)
object Test {
/**
Returns a list of `Test` objects that pass the given criteria.
@param tests some source of tests that we can loop over one at a
time.
@param condition checks whether a `Test` object should go into our
output list.
*/
def runningList(
tests: Iterable[Test])(condition: Test => Boolean): List[Test] =
tests.filter(condition).toList
}

您可以像这样使用它(例如):

Test.runningList(testsSource) { test => test.c > 0 && test.d < 100 }

正如你在这里看到的,我使用了一些 Scala 功能,比如可迭代对象及其列表转换方法、多参数列表方法、一类函数、函数作为最后一个参数 DSL 等。如果您对这些主题有更多疑问,我建议您使用 Scala 教程。

相关内容

  • 没有找到相关文章

最新更新