简体   繁体   中英

How to access a class's type parameter in Scala

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)
}

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.

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM