以下代码导入相同的符号两次,因为它导入了两个不同的对象,并且都将其导出:
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
的一些实现细节对编译器隐藏了这一点。
我该如何解决这个问题?
动机:在我的项目中,我有几个对象,它们都导出一组有用的扩展函数,以便任何使用这些对象的人都可以使用这些扩展,而无需显式导入它们。
只是不要在一处导出/导入不明确的定义:
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 个不同位置导出的相同定义是不同的 - 这可以随时更改,而且它们仅在当前实现细节中引用相同的对象。