返回内部类对象的列表

stackoverflowuser2010

我从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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章