Simple question, I have code like this:
class Context[A] {
def t: A
}
object Context {
implicit object StandardContext extends Context[SomeObject] {
def t = SomeObject
}
}
SomeObject
is an object
that holds values and functions that I would like to access in my Context
. Unfortunately the different types for A
I would like to include do not have a common parent class, 开发者_如何学编程other than java.lang.Object
.
SomeObject
is defined like this:
final object SomeObject {
def func1 = ...
def func2 = ...
}
In some code that's not mine. But the Scala compiler complains SomeObject is not a value
when I try the thing above. As far as I know it, an object
in scala is a singleton class, so it would be a type, yes, but also a value, the only value of its own type.
What I wanna do is stuff like this:
class Foo[A](bar: Int)(implicit context: Context[A]) {
def baz = context.t.baz
}
Anyone can tell me how to solve this or have a better idea of solving it?
implicit object StandardContext extends Context[SomeObject] {
def t = SomeObject
The first SomeObject is a type, a type-parameter for Context, but in the second row it is used as if it were a variable.
Think of
... List [Int] {
def x = Int // fail
Int is a type, not a variable, so x
can't return Int
, it could only return an integer.
Your non-code description already asserts that the type param A
of Context
will be AnyRef
, and so renders it useless. Context
is essentially:
class Context { def t: AnyRef }
You certainly can't call context.t.baz
on some instance of this.
Given that there's no helpful parent class available, you might want to roll your own, via structural types. type classes may also be a good fit, but it's impossible to advise better without knowing the actual problem you're trying to solve.
Anyone ... have a better idea of solving it?
How about lifting the wanted function from the object and using that as your implicit?
scala> object SomeObject {
| def baz = "hi"
| }
defined module SomeObject
scala> implicit val baz = SomeObject.baz _
baz: () => java.lang.String = <function0>
scala> class Foo(bar: Int)(implicit baz: () => String) {
| def bazme = baz()
| }
defined class Foo
scala> new Foo(100).bazme
res2: String = hi
If the function is not of a consistent type, then the function type itself could be parameterised. E.G.
class Foo[A](bar: Int)(implicit baz: () => A) // or
class Foo[A](bar: Int)(implicit baz: A) // or
class Foo[A, B](bar: Int)(implicit baz: A => B) // etc
Using this approach the implicit can be lifted from an Object, or an instance. It doesn't matter.
精彩评论