The problem with shared collections in Scala

I am puzzled by how to solve this problem in Scala. In Java, I would refuse generics or use casts, but Scala is more strict. Here is what I have.

  • An abstract base class Factory[+F <: Factory[F]]and some specific implementations that are irrelevant here. This is covariant. This class has a method that creates products - see the next point.
  • An abstract base class Product[+F <: Factory[F]]representing a factory work. They are also covariant and read-only. Any particular factory produces exactly one type of product (i.e. there are no several different subtypes - FooFactory produces FooProduct, BarFactory produces BarProduct, etc.).
  • I should have a set of factories containing specific instances (Captain Obvious is implied here). Currently it is Iterable[Factory[_]]. This is the first part of the trouble. Scala seems to understand _here how Any, oblivious to the restriction F <: Factory[F]on the type itself.
  • I have an aggregated factory method that each factory requests to get its product with the same arguments. The result is a map of factories for their products, currently encoded as Map[Factory[_],Product[_]]well as tested Map[Factory[_],Product[Factory[_]]]. This is another part in which I am in trouble. The first is _disconnected from the second _, and both of them seem implied as Any.

What I can not do is create this map. It may or may not be important, but I do it (and should do it) using another method similar to the syntax construct. It comes from the line and:

  • Invokes the declared method (name it gather[B](fun: A => B): Map[A,B]here, not implemented in the attribute itself and in the typical order), which receives a collection of factories. The actual type of factory is common and unknown.
  • Iterates over this common set and performs the function passed to it. This function actually calls the factory method.
  • Returns immutable Mapfrom F to P

'gather', , . Map[Factory[_],Product[_]], _ F <: Factory[F] ... _, Factory[Factory[Factory[Factory......(infinitely many times)]]]]]].... , .

, !

+3
4

_ - , , . , , , , . , Scala , _ Any, , _ - Any, Nothing - .

, Iterable[Factory[_]] Iterable[Factory[T]] forSome { type T }. Iterable[Factory[T]] forSome { type T <: Factory[T] }, , , Map[Factory[T], Product[T]] forSome { type T <: Factory[T] }.

, , , . , , , , . , , :

abstract class Factory {
    type T <: Factory
}
+5

, Scala . .

, Factory Product , . , FactoryBase, Factory. Iterable[FactoryBase].

, Product Factory. , . A Factory a Product, , , . , .

, , , :

FactoryBase
   Factory[+F <: Factory[F,P], +P <: Product[F,P]] <: FactoryBase
      FooFactory <: Factory[FooFactory, FooProduct]
ProductBase
   Product[+F <: Factory[F,P], +P <: Product[F,P]] <: ProductBase
      FooProduct <: Product[FooFactory, FooProduct]

- , .

, , . . , , . . , , Map[FactoryBase, ProductBase]. , FooFactory FooProduct, BarProduct, Map . , Product Factory. , Map. n - - factory .

, , . , .

+2

, , - :

gather[A : Factory, B : Factory](fun: A => B): Map[A,B]
+1

.

Scala, .

, , , . , :

FactoryBase
   Factory[+F <: Factory[F,P], +P <: Product[F,P]] <: FactoryBase
      SomeFactoryGroup[+F <: SomeFactoryGroup[F,P], +P <: SomeProductGroup[F,P]] <: Factory[SomeFactoryGroup, SomeProductGroup]
        FooFactory <: SomeFactoryGroup[FooFactory, FooProduct]
ProductBase
   Product[+F <: Factory[F,P], +P <: Product[F,P]] <: ProductBase
      SomeFactoryGroup[+F <: SomeFactoryGroup[F,P], +P <: SomeProductGroup[F,P]] <: Product[SomeFactoryGroup, SomeProductGroup]
        FooProduct <: SomeProductGroup[FooFactory, FooProduct]

, . , FactoryBase ProductBase. , , . FactoryBase, (SomeFactory | exist F <: Factory[F,P], exist P <: Product[F,P], SomeFactory <: F) ( Scala, ). , (, ). , FactoryBase Iterable[FactoryBase] .

. , factory (, , ). , factory , , factory .

- , : , ( ) . , :

productionrun.lookup(factory) = productionrun.mapFromFactoryToProduct.lookup(factory)

, FactoryBase ProductBase. . A (, ) B. , . , . , . , , , , . , ? , , .

: ( ) .

factory.lookup(productionrun) = factory.mapFromProductionRunToProduct.lookup(productionrun)

. , . ( , , , ). ( factory). , .

So to summarize. Have a class PRthat represents a production run. Create a method Factory[F,P].findProduct(pr:PR)->Product[F,P]implemented with Map[PR, Product[F,P]]. Ask the method makeProductto accept the value PRand add the result to the map using this value PR. You can wrap it in a method PR.lookUpProductByFactory[F,P](f:Factory[F,P])->Product[F,P]or some if you want. Also, wrap it in FactoryBase.findProduct(pr:PR)->ProductBaseand wrap it in PR.lookUpProductBaseByFactoryBase(f:FactoryBase)->ProductBase.

What is it. I hope these two solutions suit your needs.

+1
source

All Articles