我们可以在Scala中进行条件导入吗?
假设我有以下代码:我们可以在Scala中进行条件导入吗?,scala,Scala,假设我有以下代码: package my class Foo class Bar extends Foo object Chooser { val isFoo = true } 我将Foo导入为: 我希望能够做到以下几点: 如果Chooser.isFoo,则: 其他: 我在代码中使用了Foo,如下所示: object MyObj { val a = new MyClass // ... } Scala是否有任何隐藏的特性可以让我在不修改MyObj代码的情况下使用Bar代
package my
class Foo
class Bar extends Foo
object Chooser {
val isFoo = true
}
我将Foo导入为:
我希望能够做到以下几点:
如果Chooser.isFoo,则:
其他:
我在代码中使用了Foo,如下所示:
object MyObj {
val a = new MyClass
// ...
}
Scala是否有任何隐藏的特性可以让我在不修改MyObj代码的情况下使用Bar代替Foo。还有,将来设计这样的代码的最佳方法是什么,这样扩展就很容易了?没有,但我猜您对运行时的不同实现比对条件类型导入更感兴趣。您的Chooser.isFoo听起来像是在运行时发生的,而不是在类型系统中发生的 由于Foo和Bar的常见类型是Foo,因此可以使用以下示例:
val a: Foo =
if (Chooser.isFoo) new my.Foo
else new my.Bar
基于编辑进行编辑:您可以通过使用抽象类型或类型参数来延迟选择,如下所示:
class MyObj[T :> Foo] {
val a: T
}
val anInstance = new MyObj[Foo]
val anotherInstance = new MyObj[Bar]
注意类型绑定,它说T必须是Foo的子类,否则你就不知道用T可以做什么。碰巧看到这篇老文章&有点奇怪为什么它不能在Scala中进行条件导入?可能是旧版本的限制,不确定?但是请看,我们可以在任何地方导入scala代码 对于您的场景,可以是: try.scala: 运行输出:
或者只是添加一个方法来选择def getObj=if isFoo new Foo else new Bar,然后让MyObj调用它。这将使MyObj类不再需要知道Foo的子类型。我需要条件导入,因为我使用的是Bar所需的某些库,这些库可以在一种情况下使用,但由于许可证的原因,无法在另一种情况下使用。如果我使用选择器,那么即使没有使用Bar,也需要提供这些库,如果我没有弄错的话。即使这是一个许可问题,您仍然只是在执行运行时功能检测。如果可以,可以分发Bar所需的库。在运行时,检测库是否存在。如果是,则返回一个Bar,否则返回一个Foo。Java应用程序通常使用服务提供者接口来实现这一点,Scala没有理由不能使用相同的JVM特性。基于Chooser.isFoo的选择发生在导入发生后的运行时。所以你所要求的是行不通的。如果您能提供一个facade来实现一个同时使用Foo和Bar库的API,那么将您的其余代码编写到该API中。然后提供两个实现facadeforbar,与Bar库绑定,facadeforfoo,与Foo库绑定?在后台,它需要两个库来编译。然而,我想要的是跳过编译时不需要的库。
object MyObj {
val a = new MyClass
// ...
}
val a: Foo =
if (Chooser.isFoo) new my.Foo
else new my.Bar
class MyObj[T :> Foo] {
val a: T
}
val anInstance = new MyObj[Foo]
val anotherInstance = new MyObj[Bar]
package my
class Foo {
}
class Bar extends Foo
object Chooser {
val isFoo = true
}
object MyObj extends App {
if (Chooser.isFoo) {
import my.{Foo => MyClass}
val a = new MyClass
println(a)
} else {
import my.{Bar => MyClass}
val a = new MyClass
println(a)
}
}
C:\abc\abc>scalac try.scala
C:\abc\abc>scala my.MyObj
my.Foo@6f4a47c7