Restriction on types of keys / values ​​of a card, how to connect them?

In Scala code, I have

val pendingServices = new ConcurrentHashMap[String, JMap[Class[_ <: Service], Service]]()

On the caller side, Java using looks like

Service$.MODULE$.pendingServices().get("key").put(Foo.class, new Foo()); 

I can also get an instance of some class Service

Service$.MODULE$.pendingServices().get("key").get(Foo.class)

or from Scala,

Service.pendingServices.get("key").get(classOf[Foo])

Problem: you can put unrelated Servicees on the map , for example

Service$.MODULE$.pendingServices().get("key").put(Bar.class, new Foo());

If Fooand Barare both expanding Service. So, how can I limit Class[_ <: Serviceand Servicefrom the definition to share the same Service?

I want to demonstrate to my employees some cases where a system like Scala really helps. Tried the lambdas type, but my fu type is not strong enough.

+4
source share
2 answers

​​ scala

import scala.collection.mutable.{HashMap β‡’ MHMap,  SynchronizedMap}
import scala.reflect.{ClassTag, classTag}

class Service

case class Foo() extends Service
case class Bar() extends Service

object Service {
  object pendingServices {
    private val backing = (new MHMap[String, Map[Class[_], Service]] with SynchronizedMap)
        .withDefaultValue(Map.empty)

    def update[T <: Service : ClassTag](name: String, service: T): Unit =
      backing(name) += classTag[T].runtimeClass β†’ service

    def apply[T <: Service : ClassTag](name: String): T =
      backing(name)(classTag[T].runtimeClass).asInstanceOf[T]
  }
}

scala

val foo = new Foo
val bar = new Bar

pendingServices("baz") = foo
pendingServices("baz") = bar

println(pendingServices[Foo]("baz")) // Foo()
println(pendingServices[Bar]("baz")) // Bar()

java

final Foo foo = new Foo();
final Bar bar = new Bar();
Service.pendingServices$.MODULE$.update("baz", foo, ClassTag$.MODULE$.apply(Foo.class));
Service.pendingServices$.MODULE$.update("baz", bar, ClassTag$.MODULE$.apply(Bar.class));

System.out.println(Service.pendingServices$.MODULE$.<Foo>apply("baz", ClassTag$.MODULE$.apply(Foo.class))); // Foo()
System.out.println(Service.pendingServices$.MODULE$.<Bar>apply("baz", ClassTag$.MODULE$.apply(Bar.class))); // Bar()

- scala,

+3

, - . - Java:

public class ServiceRepository {

    private Map<Class<?>, Object> repo = new HashMap<>();

    public <T> void put(Class<T> clazz, T service) {
         repo.put(clazz, service);
    }

    public <T> T get(Class<T> clazz) {
        return (T) repo.get(clazz);
    }

}
+2

Source: https://habr.com/ru/post/1614746/


All Articles