Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dart multiple upper bounds

Tags:

dart

I need to implement a solution using generics that implements 3 interfaces, but as far as I can tell, generics in dart only supports 1 upper bound?

I have a model that looks like this:

abstract class Category implements Built<Category, CategoryBuilder>, Identifiable, Mapable {
   ...
}

The contents of the 3 interfaces is not really relevant, and what I'm trying to do, is construct a class that can process this in generic form.

What I want is something like this:

abstract class BaseDB<T extends Built<T, R> & Identifiable & Mapable, R extends Builder<T, R>> {
   process(T entity) {
      print(entity.id); // From Identifiable
      entity.toMap(); // From Mapable
      // ... etc
   }
}

I know this is possible in both Typescript and Java, but I'm fairly new at Dart. Anyone know?

like image 466
DarkNeuron Avatar asked Aug 31 '26 23:08

DarkNeuron


1 Answers

This is not possible in Dart. You can only put one bound on a type variable.

The bound of a Dart type variable is used to check which operations you can do on an object of the type parameter type. Example:

String something<T extends num>(T value) {
  return value.abs().toString();
}

You are allowed to call abs() on value because we know that all instances of value are numbers, and num has an abs method.

If you can write <T extends Foo & Bar>, then there is no simple type in the Dart type system that can describe objects of type T. Dart does not have intersection types (the intersection type Foo & Bar would be a supertype of all types that are subtypes of both Foo and Bar, and a subtype of both Foo and Bar). If Foo declares Baz method(), Bar declares Qux method(), and value has type T, what is the type of value.method()? (It would either be disallowed, or the type would be Baz & Qux). This shows that allowing & in type variable bounds leaks intersection types into the remaining type system, and since Dart does not have intersection types, it also does not have multiple bounds on type variables.

When you declare a class, FooBar, implementing both Foo and Bar, you have the same issue: You need to figure out what method returns. However, the language requires you to write that solution into your class, to find some valid return type for FooBar.method, because otherwise the FooBar class declaration is not valid. It requires a user to find a solution to "find a subclass of both Baz and Qux".

like image 156
lrn Avatar answered Sep 04 '26 23:09

lrn