Как прокси-вызов для hashmap без потери типа - PullRequest
2 голосов
/ 02 февраля 2012

В приведенном ниже коде я получаю правильный тип свойства (PropertyA), когда получаю его прямо из hashmap.

Когда я передаю прокси через этот вызов через метод get в ClassAbstract typeis PropertyAbstract[_ <: A]

Есть ли способ прокси для вызова хеш-карты и сохранения правильного типа?

Другой вопрос, как я могу добавить объекты в массив revs с проверкой типа?

class A
class B extends A
class C extends A

abstract class PropertyAbstract[T] {
  val revs = new java.util.ArrayList[T]
}

class PropertyA extends PropertyAbstract[B]
class PropertyB extends PropertyAbstract[C]

abstract class ClassAbstract {
  val props: scala.collection.immutable.HashMap[String, PropertyAbstract[_ <: A]]
  def get(prop: String) = props.get(prop).get
}

class Class extends ClassAbstract {
  val props = collection.immutable.HashMap(
      "prop1" -> new PropertyA,
      "prop2" -> new PropertyB
  )
}

object Test extends App {
  val the_class = new Class
  val proxied_prop = the_class.get("prop1")
  val direct_prop =  the_class.props.get("prop1").get

  // wont compile (found: B     required: _$1 <: A)
  proxied_prop.revs.add(new B) 
  // wont compile (found: B     required: C with B)
  direct_prop.revs.add(new B)
}

Требуемый результат заключается в том, что я могу добавить элемент типа B в prop1, но не элемент типа C

Ответы [ 2 ]

3 голосов
/ 02 февраля 2012

Проблема в том, что get определено в ClassAbstract и реквизиты конкретно определены в Class и имеют дальнейшее уточнение типа, которое недоступно для ClassAbstract . Нам нужно предоставить способ передачи этой дополнительной информации о типе из Class обратно в ClassAbstract. Ниже приведен один из способов сделать это.

abstract class ClassAbstract[P <: PropertyAbstract[_ <: A]] {
  val props: scala.collection.immutable.HashMap[String,P]
  def get(prop: String) = props.get(prop)
}

class Class extends ClassAbstract[Property] {
  val props = collection.immutable.HashMap(
      "prop" -> new Property
  )
}

Это заставляет прямой вызов get возвращать что-то типа Property.

2 голосов
/ 02 февраля 2012

Кажется, что вы хотите, по сути, типизированную карту. Совершенно очевидно, что то, что вы пытаетесь сделать, просто не может работать. Когда вы звоните get, вы получаете PropertyAbstract[X] для неизвестного X (за исключением того, что это подтип A). Как вы можете тогда предположить, что это займет B с?

Решение состоит в том, чтобы ваш PropertyAbstract был контравариантным , но это означает, что он не может быть изменяемой коллекцией каким-либо разумным способом (она может быть изменяемой, конечно, но Вы можете выйти, будет A).

scala> class A; class B extends A; class C extends A
defined class A
defined class B
defined class C

scala> abstract class PropertyAbstract[-T] { val revs = new java.util.ArrayList[AnyRef] }
defined class PropertyAbstract

scala> class PropertyA extends PropertyAbstract[B]; class PropertyB extends PropertyAbstract[C]
defined class PropertyA
defined class PropertyB

scala> abstract class ClassAbstract {
   | val props: Map[String, PropertyAbstract[_ <: A]]
   | def get(prop: String) = (props get prop).get
   | }
defined class ClassAbstract

scala> class Class extends ClassAbstract { val props = Map("prop1" -> new PropertyA, "prop2" -> new PropertyB) }
defined class Class

scala>  val the_class = new Class
the_class: Class = Class@298508

scala> val proxied_prop = the_class.get("prop1")
proxied_prop: PropertyAbstract[_ <: A] = PropertyA@a269e2

scala> val direct_prop =  the_class.props.get("prop1").get
direct_prop: PropertyAbstract[C with B] = PropertyA@a269e2

Следующая компиляция:

scala> proxied_prop.revs.add(new B)
res0: Boolean = true

scala> direct_prop.revs.add(new B)
res1: Boolean = true

Но, конечно, вы могли бы положить туда что угодно!

Возможно, вам стоит взглянуть на бесформенного Майлза Сабина для того, что вы можете делать с точки зрения разнородных коллекций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...