user3211306
user3211306

Reputation: 382

Declaring a Type variable that must be a subclass - Dart

Kotlin code:

Class<? extends Model> someType();

I want to do the equivalent in Dart where I can declare a variable that stores a class that must extend from the Model class.

So far, I only know how to declare a variable that stores a generic class in a Dart variable via:

Type someType; 

But I want "someType" to only be Types/Classes that extend from the Model class.

Upvotes: 1

Views: 532

Answers (2)

lrn
lrn

Reputation: 71623

Dart Type objects are not generic. There is only one Type class, and no way to compare them for subtyping. The Type objects are also fairly useless for anything else.

You should probably not be using Type objects at all.

They are rarely what you need because they are so completely useless in most situations. If you are not using dart:mirrors, I recommend no using Type objects at all.

So, why do you want to store a Type value to begin with? Is there some way you could store it as a type variable instead?

Say, you need to know the type in order to create a list of that type. Type objects can't do that, but a proper generic type variable can be used.

Consider having a class like;

class MyType<T> {
  const MyType();
  /// Perform [action] with [T] as type argument.
  R callWithType<R>(R Function<T>() action) => action<T>();
  
  // Checks and casts.
  bool isInstance(Object o) => o is T;
  T cast(Object o) => o as T;
  T safeCast(Object o) => o is T ? o : null;

  // Subtyping checks.
  bool operator >=(MyType other) => other is MyType<T>;
  bool operator <=(MyType other) => other >= this;
  bool operator <(MyType other) => other >= this && !(this >= other);
  bool operator >(MyType other) => this >= other && !(other >= this);
  bool operator ==(Object other) => 
      other is MyType && this >= other && other >= this;
  int get hashCode => T.hashCode;

  // Whatever other operations you want.
}

Then you can use that kind of "type representation object" instead of a Type object, and you can actually use it for practical operations. You can then also ask for a MyType object for a restricted type:

MyType<Model> modelType; // Only `MyType` objects for `Model`s
// or 
void withType<T extends Model>(MyType<T> type, ...) ...

You can still only do things that are supported by type variables. You can't create a new instance of T or look up static members of the class, those only work using the actual class.

Upvotes: 3

dustinnoyes
dustinnoyes

Reputation: 209

Abstract classes cannot be instantiated directly, and therefore any variable typed with an abstract class could only be initialized with a subclass. This might suit your purpose.

Upvotes: 1

Related Questions