Как да получите достъп до параметър тип на клас в Scala

Имам тип-параметризиран абстрактен клас, който съдържа val и метод, които и двата използват своя тип параметър

abstract class Foo[T](val state: T){
  def foo(arg: T){
    ...
  }
}

Имам и клас, който разширява този абстрактен клас и предоставя параметър тип и стойност за state

class Bar(myNumber: Int) extends Foo[Int](myNumber){
   ...
}

Предавам екземпляр на Bar на друг клас, който приема всеки подклас на Foo, и бих искал да извикам метода foo на state, но срещам някои проблеми:

class Baz(val f: Foo[_]){
    f.foo(f.state)
}

Това дава грешката:

<console>:8: error: type mismatch;
 found   : Baz.this.f.state.type (with underlying type _$1)
 required: _$1
         f.foo(f.state)

Има ли някакъв начин да дадете на Baz знания за параметъра тип на Bar, така че да се компилира правилно? Или дори това е, което искам да направя?

Редактиране

За да поясня, имам много класове, подобни на Bar, които разширяват Foo и предоставят свой собствен тип параметър, състояние и реализация на foo. Бих искал потребителите на моята библиотека да могат да предават който и да е от тях на Baz, без да се притесняват за параметъра на типа T, тъй като това е просто детайл на изпълнението на всеки подклас на Foo.

Така че силно бих предпочел да не правя това:

class Baz[T](val f: Foo[T]){
  f.foo(f.state)
}

person DLaw    schedule 25.05.2014    source източник
comment
Екзистенциали, считани за вредни. Тази тема обхваща защо и различни решения които биха могли да се използват.   -  person ggovan    schedule 25.05.2014
comment
Този въпрос е различен, защото питащият уточнява тип T и иска екзистенциалният тип да бъде негов суперклас. Във въпроса си искам да го игнорирам изцяло. Освен това опитах техния отговор и не проработи.   -  person DLaw    schedule 26.05.2014


Отговори (2)


Просто се нуждаете от

def fooOnState[T](ft: Foo[T]) = ft.foo(ft.state)

извикването му с Foo[_] е добре.

Все пак екзистенциалите е най-добре да се избягват през повечето време, но това зависи от вашия реален код.

person Didier Dupont    schedule 25.05.2014
comment
Това ще свърши работа, но тогава как ще получа достъп до T, което трябва да извикам fooOnState? Имам много различни подкласове от Foo всеки със собствен T и т.н... - person DLaw; 26.05.2014
comment
Не съм сигурен, че разбирам, можете да извикате fooOnState, като му предадете Foo[_], във вашия код просто извикайте fooOnState(f) вместо f.foo(f.state) не е необходимо да знаете T за това. - person Didier Dupont; 26.05.2014
comment
Моите извинения, не знаех, че можете да пропуснете този тип параметър, когато се обаждате. Прието! - person DLaw; 26.05.2014

Замяната на параметъра на типа с "член на типа" в черта ще ви позволи да напишете общ код, който работи за всички типове състояния, за сметка на малко многословие, за да посочите члена на типа във всеки подклас:

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
}
person Ben Kovitz    schedule 25.05.2014