简体   繁体   中英

Defining a type to be a `Comparable` in 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 (ie 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 ?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM