如何处理相同符号的重复导出?

问题描述 投票:0回答:1

以下代码导入相同的符号两次,因为它导入了两个不同的对象,并且都将其导出:

object Ext:
  def backwards(s: String): String = s.reverse
  
object A:
  export Ext.*

object B:
  export Ext.*
  
import A.*
import B.*

backwards("Hello")

错误是:

向后的引用是不明确的。 它都是通过 import A._ 导入的 并随后通过 import B._

导入

最终是相同的符号,因此实际上没有歧义,但我猜

export
的一些实现细节对编译器隐藏了这一点。

我该如何解决这个问题?

动机:在我的项目中,我有几个对象,它们都导出一组有用的扩展函数,以便任何使用这些对象的人都可以使用这些扩展,而无需显式导入它们。

scala scala-3
1个回答
0
投票

只是不要在一处导出/导入不明确的定义:

import A.*
import B.{backwards => _, *}

backwards("Hello")
import A.{backwards => _, *}
import B.*

backwards("Hello")

object A:
  export Ext.*

object B:
  export Ext.{backwards => _, *}
object A:
  export Ext.{backwards => _, *}

object B:
  export Ext.*

或者不要跳过,而是重命名:

object A:
  export Ext.{backwards => backwardsA, *}

object B:
  export Ext.{backwards => backwardsB, *}

最终它是相同的符号,因此实际上没有歧义,但我猜导出的一些实现细节对编译器隐藏了这一点。

export
仅定义新的
val
def
、类型别名等。从技术上讲,它是复制粘贴每个签名并向原始定义添加委托的快捷方式。您可以拥有
export foo.*
,然后修改它以跳过带有
export foo.{skipped => _, *}
的定义,以便您可以手动实现它,并且 - 只要签名相同 - 代码就不会注意到差异。因此,您不能将
export
视为某些神奇的批处理别名。这是一个代码生成器。像这样对待它:

trait Foo:
  def bar(baz: Baz): Bar

def addToString(foo: Foo)(str: String): Foo =
  new Foo:
    export foo.{toString => _, *} // generates definitions required by the interface
    override def toString = str

突然明白了。这也是有道理的,为什么任何分析都认为通过 2 个不同位置导出的相同定义是不同的 - 这可以随时更改,而且它们仅在当前实现细节中引用相同的对象。

© www.soinside.com 2019 - 2024. All rights reserved.