返回一个内部类对象列表
返回一个内部类对象列表
我正在从Java转向Scala。我想创建一个定义了(1)内部Inner
case类和(2)返回Inner
对象列表的方法的Outer
类。请注意,在Java中,内部类的类型将明确为Outer.Inner
。
我发现有两种引用内部类类型的方法:outerObject.Inner
或Outer#Inner
,如这里所讨论的。我应该使用哪种方法返回一个内部对象列表?
例如,我可以这样实现我的Scala代码:
// Implementation 1 class Outer { case class Inner(id: String) def build(input: List[String]): List[Inner] = { var result = scala.collection.mutable.ListBuffer[Inner]() input.foreach { s => val inner = Inner(s) result += inner } result.toList } }
或者这样实现:
// Implementation 2 class Outer { case class Inner(id: String) def build(input: List[String]): List[Outer#Inner] = { var result = scala.collection.mutable.ListBuffer[Outer#Inner]() input.foreach { s => val inner = Inner(s) result += inner } result.toList } }
唯一的区别是build()
返回List[Inner]
或List[Outer#Inner]
。
假设我的代码的调用者运行以下代码:
val input: List[String] = List("A", "B", "C") val outer = new Outer() val output = outer.build(input)
然后对于实现1,调用者看到的输出是:
output: List[outer.Inner] = List(Inner(A), Inner(B), Inner(C))
而对于实现2,调用者看到的是:
output: List[Outer#Inner] = List(Inner(A), Inner(B), Inner(C))
在Scala中,哪种方法是首选(惯用)的方法?
相关问题:
问题的出现原因是在于对于内部类对象列表的返回类型的选择。在给定的示例中,有两种实现方式。第一种实现方式是直接返回Inner
类的列表,而第二种实现方式是返回Outer#Inner
类的列表。
对于这两种实现方式,它们的差异在于返回的内部类对象列表的类型约束。第一种实现方式返回的是一种“路径依赖”的Inner
类的列表,它只能与创建它的Outer
实例相关联。而第二种实现方式返回的Inner
类的类型没有与特定的Outer
实例相关联的限制,可以在任何需要Inner
实例的地方使用。因此,第二种方式是更加严格的,而第一种方式则相对不那么严格。
为了更好地解释这两种实现方式的差异,给出了另一个示例。在这个示例中,分别使用这两种实现方式创建了Outer
实例,并对它们进行操作。通过这个示例可以看出,在使用第一种实现方式的情况下,最后一个语句会导致类型不匹配的错误,而在使用第二种实现方式的情况下则不会出错。
此外,还提到了第一种实现方式是第二种实现方式的子类型,可以将第一种实现方式返回的Inner
实例传递给需要Inner
实例的函数,但反过来则不行。
对于返回Inner
实例的操作,应该返回“路径依赖”的形式,因为它也是通用形式的子类型,提供了最大的灵活性。然而,更重要的是接受现有Inner
实例时使用的类型签名:
- 如果操作(属于Outer
实例)在Inner
实例和自身之间具有强耦合关系(Inner
实例通常会保持对其Outer
实例的引用),那么只应该接受“路径依赖”的形式。
- 然而,如果操作适用于任何Inner
实例,包括接受方法根本不属于Outer
的情况,那么应该接受通用形式。
最后,总结一下:
- 返回Inner
实例的方法应该返回“路径依赖”的形式,以提供最大的灵活性。
- 接受现有Inner
实例的方法应根据实际情况选择使用“路径依赖”的形式或通用形式。
Scala的“路径依赖的内部类的列表”有什么优点?它解决了什么问题?
在这个特定的示例中,使用“路径依赖”的形式明显没有明显的好处。实际上,它可能引起比解决更多的问题。然而,每个Inner
实例也与它所属的Outer
实例相关联。假设Outer
还有其他的数据成员,Inner
通过该引用对这些数据成员进行操作。如果将一个由一个Outer
实例创建的Inner
实例传递给另一个Outer
实例,它仍然访问原始Outer
的成员,这可能会引起混淆。
除了使用内部类之外,还有另一种通过type
语句声明“路径依赖”类型的方式,这种方式不一定依赖于内部类。详细信息可以参考《Programming in Scala》一书的第20章(特别是20.7节)。
最后,对于所有额外的注释表示歉意!:-)只是想让您知道我更新了答案,以更好地解释何时使用每种类型。实际上,区分它们应该是相当容易的。