Reputation: 821
I have a type-parameterized abstract class that contains a val and a method that both use its type parameter
abstract class Foo[T](val state: T){
def foo(arg: T){
...
}
}
I also have a class that extends this abstract class and provides the type parameter and a value for state
class Bar(myNumber: Int) extends Foo[Int](myNumber){
...
}
I pass an instance of Bar
to another class that accepts any subclass of Foo
, and I would like to call the method foo
on state
, but I'm running into some trouble:
class Baz(val f: Foo[_]){
f.foo(f.state)
}
This gives the error:
<console>:8: error: type mismatch;
found : Baz.this.f.state.type (with underlying type _$1)
required: _$1
f.foo(f.state)
Is there any way to give Baz
knowledge of Bar
's type parameter so that it compiles correctly? Or is that even what I want to do?
Edit
To clarify, I have many classes similar to Bar
that extend Foo
and provide their own type parameter, state, and implementation of foo
. I would like users of my library to be able to pass any of them to Baz
without worrying about the type parameter T
since its just an implementation detail of each subclass of Foo
.
So I would strongly prefer not to do this:
class Baz[T](val f: Foo[T]){
f.foo(f.state)
}
Upvotes: 3
Views: 804
Reputation: 5030
Replacing the type parameter with a "type member" in a trait would let you write generic code that works for all state types, at the expense of a little verbosity to specify the type member in each subclass:
trait Foo {
type StateT // this is the "type member"
val state: StateT
def foo(arg: StateT): Unit
}
class Bar(myNumber: Int) extends Foo {
type StateT = Int // this is the verbose part
override val state = myNumber // this, too
override def foo(arg: StateT) { /* something specific here */ }
}
class Baz(val f: Foo) {
f.foo(f.state) // generic code, works on any Foo subclass
}
Upvotes: 0
Reputation: 29548
You just need a
def fooOnState[T](ft: Foo[T]) = ft.foo(ft.state)
calling it with a Foo[_]
is ok.
Still, existentials are best avoided most of the time, but it depends on your real code.
Upvotes: 2