我从Java到Scala。我想创建一个Outer
定义(1)内部Inner
案例类和(2)返回Inner
对象列表的方法的类。请注意,在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中哪种首选(惯用的)方法是?
相关问题:
欢迎来到Scala!
首先,有一种更干净,更有效的方法来创建您的实现,下面将向我展示。
// Implementation 1
class Outer {
case class Inner(id: String)
def build(input: List[String]): List[Inner] = input.map(s => Inner(s))
}
// Implementation 2
class Outer {
case class Inner(id: String)
def build(input: List[String]): List[Outer#Inner] = input.map(s => Inner(s))
}
使用map
意味着您不需要任何难看的var
元素,也不需要构建一个ListBuffer
然后将其转换为List
。
至于哪个更惯用,则取决于您要执行的操作。第一种形式返回s的路径相关列表Inner
。可以限制它与Outer
创建它的实例一起使用。在第二种形式中,Inner
返回的类型不能绑定到特定Outer
实例,但是可以在任何 Inner
可接受实例的地方使用。因此,后者更具限制性,而前者则更具限制性。考虑以下:
// Implementation 1
class Outer {
case class Inner(id: String)
def build(input: List[String]): List[Inner] = input.map(s => Inner(s))
def getId(inner: Inner): String = inner.id
}
// Implementation 2
class Outer {
case class Inner(id: String)
def build(input: List[String]): List[Outer#Inner] = input.map(s => Inner(s))
def getId(inner: Outer#Inner): String = inner.id
}
然后尝试对每个实现评估以下内容:
val input: List[String] = List("A", "B", "C")
val outer = new Outer()
val output = outer.build(input)
val outer2 = new Outer()
outer2.getId(output.head)
在实现1中,您会在最后一条语句中看到类型不匹配错误,但在实现2中则不会。
更新:我忘了提及这一点(可能是避免进一步的混乱),但是与路径相关的版本是常规版本的子类型。(这是this.Inner
的子类型Outer#Inner
。)因此,您可以将依赖Inner
于路径的版本传递给需要any 的函数,反之则不需要Inner
。
也就是说,以下将起作用:
class Outer {
case class Inner(id: String)
def build(input: List[String]): List[Inner] = input.map(Inner)
def getId(inner: Outer#Inner): String = inner.id
}
val input: List[String] = List("A", "B", "C")
val outer = new Outer()
val output = outer.build(input)
val outer2 = new Outer()
outer2.getId(output.head)
但这不会:
class Outer {
case class Inner(id: String)
def build(input: List[String]): List[Outer#Inner] = input.map(Inner)
def getId(inner: Inner): String = inner.id
}
val input: List[String] = List("A", "B", "C")
val outer = new Outer()
val output = outer.build(input)
val outer2 = new Outer()
outer2.getId(output.head)
(请注意,build
在每种方法中,我还使用了偶数形式的方法。)
所以,总结一下...
Outer
返回新Inner
实例的函数(属于)应返回与路径有关的形式,因为它也是通用形式的子类型,并提供最大的灵活性。(但是,请记住,Inner
可以从Outer
实例的控件外部创建可公开访问的类实例,并且可以是调用者要求的任何类型。)
但是,更重要的是接受现有Inner
实例时使用的类型签名:
如果操作(属于某个Outer
实例)在该Inner
实例Inner
与其本身之间具有很强的耦合性(并且该实例通常会维护对其Outer
实例的引用),那么提供Inner
属于另一个Outer
实例的所有物将是错误的,那么您应该只接受依赖于路径的形式。
但是,如果该操作适用于任何 Inner
实例,包括完全不属于接受方法的情况Outer
,则它应接受通用形式。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句