Reputation: 2216
My project is dependent on a library that has packages with a date in their path, like:
import xyz.abc.201301.utils._
where 201301 is a dated version.
Is there a way to declare this package name in one place so that I can refer to it in the various classes that use this dependency? That way, when the version changes I just need to change it in one place in my code.
Ideally, I'm imagining I could declare
val libVersion = 201301
in one place, and then in a client class:
import xyz.abc.$libVersion.utils._
I know that doesn't work, but is there a way to do something similar?
Upvotes: 4
Views: 1285
Reputation: 15690
You can't import dynamically, but you can invoke dynamically, using reflection.
If the library is Java, you can just use Java reflection. If Scala, the reflection library is still labelled experimental.
In either case, I'm with Madoc - don't go there unless you really have to. It's hard to write, hard to read, and if in a hot spot, slow.
Whoever packaged like this ... (words fail).
Upvotes: 3
Reputation: 5919
Short answer: no.
Long answer: You could make this work somehow. You could use a template language or preprocessor of sorts, and then create a build process that pre-processes your Scala template files before handing them over to the compiler.
But it's a bad idea. This is exactly what the dependency management systems like Maven or SBT have been developed for. The idea of a versioned module is, in your context: You keep the same package name, without a date in the package name. You create a build process that also manages your dependencies; for this, you would want to use either Maven or SBT. (The latter is more suitable for Scala.) You make sure that the code that you depend on is delivered as a separate module with a "snapshot" version, i.e. every time the dependency gets resolved, a new version is created.
In case you somehow don't want that or cannot implement such a process, I would recommend to limit the damage at least. You could create one central package that aliases all the types and objects that you need to use:
package object current_api {
// for types, i.e. traits or classes:
type SomeType = xyz.abc.201301.SomeType
// for singleton objects:
val SomeCompanionObject = xyz.abc.201301.SomeCompanionObject
}
You change your build process such that this Scala file gets generated from a template of sorts; I don't know enough about your build process to form a recommendation.
The code that uses the API can simply use the same imports:
import current_api._
// ...
val someInstance:SomeType = SomeCompanionObject.apply(arg1, arg2)
In that manner, you can limit the scope of date-dependent "imports" to just one file.
Upvotes: 5