返回一个内部类对象列表

12 浏览
0 Comments

返回一个内部类对象列表

我正在从Java转向Scala。我想创建一个定义了(1)内部Inner case类和(2)返回Inner对象列表的方法的Outer类。请注意,在Java中,内部类的类型将明确为Outer.Inner

我发现有两种引用内部类类型的方法:outerObject.InnerOuter#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中,哪种方法是首选(惯用)的方法?

相关问题:

0
0 Comments

问题的出现原因是在于对于内部类对象列表的返回类型的选择。在给定的示例中,有两种实现方式。第一种实现方式是直接返回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节)。

最后,对于所有额外的注释表示歉意!:-)只是想让您知道我更新了答案,以更好地解释何时使用每种类型。实际上,区分它们应该是相当容易的。

0