Skip to content
Anjunar/ DOCS

Inheritance

Every descriptor lists its base types by name. Registered descriptors answer subtype questions by name, without runtime classes, which is what plugin systems and polymorphic mapping need.

Base types

From the compiler

baseTypes is the linearization the compiler computed: superclasses and traits, up to Any.

reflect[Dog].baseTypes
demo.Animal, java.lang.Object, scala.Matchable, scala.Any
reflect[Dog].isSubTypeOf("demo.Animal")
true
reflect[Dog].isSubTypeOf("demo.Entity")
false
Lookups

ClassDescriptor as a directory

The ClassDescriptor object reads the global registry: find a descriptor by name, list the subtypes of a type, or check assignability between two names.

ClassDescriptor.maybeForName("demo.Cat").map(_.simpleName)
Some(Cat)
subTypesOf("demo.Animal") without Animal itself
List(Cat, Dog)
ClassDescriptor.isAssignableFrom("demo.Cat", "demo.Animal")
true
scala
ReflectRegistry.register(() => Dog("Rex")) ReflectRegistry.register(() => Cat("Tom")) ClassDescriptor.subTypesOf("demo.Animal") ClassDescriptor.isAssignableFrom("demo.Cat", "demo.Animal")
Polymorphism

Create by a name from the outside

A type name in JSON, a URL or a configuration file becomes an instance, and the check that it is an Animal happens before anything is created.

create("demo.Cat").map(_.name)
Some(Tom)
create("demo.Query")
None
scala
def create(typeName: String): Option[Animal] = Option.when(ClassDescriptor.isAssignableFrom(typeName, "demo.Animal"))(typeName) .flatMap(ReflectRegistry.createInstance) .collect { case animal: Animal => animal }