Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining a type to be a `Comparable` in Dart

Tags:

oop

dart

This question might stem from an inadequate understanding of OOP in Dart, but anyway:

I've been working on a project for which one of my base classes extends ListBase from dart:collections. It is useful in some cases I come across to be able to get the sorted indices of these List-like objects (without actually sorting them).

As a parent class I have something like (heavily simplified):

abstract class A<T> extends ListBase<T> {
  List<T> internalList;
  List<int> orderedIndices();

  ...

}

An example descendant is something like:

class B extends A<num> {

  ...

  @override
  List<int> orderedIndices() => new List<int>.generate(
    internalList.length,(i) => i)..sort(
      (i, j) => internalList[i].compareTo(internalList[j]));
}

For example, if an instance of B has [1, 5, 2, 4, 3] as its internalList then orderedIndices will return [0, 2, 4, 3, 1], as expected.

I would like to put the code that implements orderedIndices into class A's definition, however, because it would be identical in any of A's descendants as long as the specified type T is Comparable (i.e. has compareTo defined). I don't know how do this, however, because without knowing the type T, Dart has no way of knowing whether T instances are indeed Comparable and coughs at the compareTo if I try to put the code in A's definition.

Although it would work, I balk at the idea of copy-and-pasting code into descendants of the same class... Is there some way I can tell Dart in my definition of A that T will be a Comparable?

like image 322
Richard Ambler Avatar asked Sep 06 '25 03:09

Richard Ambler


1 Answers

If you want to limit T of A to types that are comparable. That's done by putting a bound on T:

abstract class A<T extends Comparable<T>> extends ListBase<T> {
  ...
  List<int> orderedIndices() => new List<int>.generate(
    internalList.length,(i) => i)..sort(
      (i, j) => internalList[i].compareTo(internalList[j]));
  ...

If not all version of A are comparable, then you can't do that. Then you can make a helper-subclass of A which is:

abstract class ComparableA<T extends Comparable<T>> extends A<T> {
   List<int> orderedIndices() => new List<int>.generate( ....
   ...
}

Then you can do class B extends ComparableA<num> ... to share the comparison behavior when it's possible, and classes extending A directly will need to make their own implementation of the method.

Finally, you could change your specifiation of orderedIndices to:

List<int> orderedIndics(int Function(T, T) compare) {
  return List.generate(internalList.length,(i) => i)..sort(
      (i, j) => compare(internalList[i], internalList[j]));
}

Then you can choose per invocation how to compare the elements of internalList. If T is Comparable, you can use Comparable.compare as the implementation.

like image 140
lrn Avatar answered Sep 07 '25 19:09

lrn