I think that in Scala Map[Class[_ <: SomeSuperClass], V] creates an immutable map such that K is classOf[T] where T is a direct or indirect subclass of SomeSuperClass. I could be wrong on this, and that may or may not be relevant to my question.
I'm finding that I can't really access the V values. How can I map the subclasses of SomeSuperClass to the V values?
For example, playing cards. In blackjack, jacks, queens and kings are all valued the same as tens. But in other games, they might have distinct values, such as that a jack is valued at 11, a queen at 12 and a king at 13.
Given an abstract Rank classes and subclasses Ace, Two, Three, ..., King, in the cards package, a class in the blackjack package could have a function like this:
def valueOf(rank: Rank): Int = rank match { case _: Ace => 11 // TODO: Figure out when value 1 case _: King => 10 case _: Queen => 10 case _: Jack => 10 case _: Ten => 10 case _: Nine => 9 case _: Eight => 8 // etc. } In Java, I would (and did) just use an enumerated type. There's something called sealed classes in Scala, but that seems to actually be a lot more trouble than enumerations in Java. Or maybe I haven't figured out how to use them properly.
But I would much prefer a more flexible approach that allows me or anyone else to add card ranks, and valuations for those ranks with a minimum of fuss (e.g., by simply subclassing Rank). Something like this:
class Valuations(val map: Map[Class[_ <: Rank], Int]) { def valueOf(rank: Rank): Int = { val key = rank.getClass if (map.contains(key) map.get(key) else { throw new NoSuchElementException("No match for " + rank.toString) } } } I can get IntelliJ to give me a green checkmark, but I can't get my unit tests to pass.
In the Java version of this, the enumerated type Rank has a value function, so you can rely on a Rank instance to have that valuation. But even if I don't want to add new card ranks, adding new mappings to values of types other than int might be clunky and not really in the spirit of the single responsibility principle.
Surely there's a more elegant solution in Scala. How can I match up these types as keys to values while maintaining the flexibility to add different subtypes without rewriting anything that already exists?
https://stackoverflow.com/questions/66880772/how-to-map-types-to-values-in-scala March 31, 2021 at 10:17AM
没有评论:
发表评论