flutterdartinheritanceextendsimplements

how to get the extender or implementer child's Type


I have a class:

abstract class Foo {
   String getName(T f);
}

and:

class Bar implements Foo {}

or

class Bar extends Foo {}

how can Foo know Bar and implement T as Bar?

UPDATE: I considered statically passing the type of the child, like:

@override
String getName<Bar>(Bar p1) {
  return p1.name;
}

this way I ran into this error: The property 'name' can't be unconditionally accessed because the receiver can be 'null'. Try making the access conditional (using '?.') or adding a null check to the target ('!'). so, I edited it to be:

@override
String getName<Bar>(Bar p1) {
  return p1!.name;
}

and now I'm getting this error: The getter 'name' isn't defined for the type 'Bar & Object'. Try importing the library that defines 'name', correcting the name to the name of an existing getter, or defining a getter or field named 'name'.

I guess the only solution, for now, is using dynamic type, like this:

abstract class Foo {
   String getName(f);
}

and

class Bar implements Foo {
  @override
  String getName(f) {
    return (f as Bar).name;
  }
}

but I'd really like to know the answer to this question.


Solution

  • abstract class Foo {
       String getName(T f);
    }
    

    should not be valid. T is not specified anywhere.

    You need to specify a place for the generic to be passed:

    abstract class Foo<T> {
       String getName(T f);
    }
    

    Then pass that generic when you extend/implement the abstract class:

    abstract class Foo<T> {
       String getName(T f);
    }
    
    class Bar implements Foo<Bar> {
      final String name = '';
      
      @override
      String getName(Bar p1) {
        return p1.name;
      }
    }
    

    If getName will always accept an implementer of Foo, you can remove the generic and instead use the covariant keyword:

    abstract class Foo {
       String getName(covariant Foo f);
    }
    
    class Bar implements Foo {
      final String name = '';
      
      @override
      String getName(Bar p1) {
        return p1.name;
      }
    }