Search code examples
flutterdarttype-safety

Compatibility of argument types


I wonder if my thinking is correct, or I'm making some big mistake. Let's have simple code:

class A { String a = "a"; }

class B extends A { String b = "b"; }

void goofy(Map<String, A> map) {
  A? item = map["b1"];
  print(item?.a);
}

void croc(dynamic map) {
  final A? item = (map as Map<String, A>)["b1"];
  print(item?.a);
}

void frape(dynamic map) {
  final A? item = (map["b1"]) as A;
  print(item?.a);
}


void main() {
  Map<String, B> mapInst = {"b1":B()};
  goofy(mapInst);
  croc(mapInst);
  frape(mapInst);
  
  Map<String, A> mapInst2 = {"b1":A()};
  goofy(mapInst);
  croc(mapInst);
  frape(mapInst);
}

All functions goofy , croc and frape works as expected. However I'm not so sure about signatures. Do Map<String,A> is compatible with Map<String,B> since B inherits from A? Or this is just a side effect, and in reality it matters that base type is Map and generics are not taken under consideration? Which syntax is recommended for situation when I want to pass Maps which can have A or B type in generic signature? Maybe just plain Map?


Solution

  • Do Map<String,A> is compatible with Map<String,B> since B inherits from A

    Yes, if B did not inherit from A, the code would not compile.

    Which syntax is recommended for situation when I want to pass Maps which can have A or B type in generic signature?

    As you said in one of your comments, you can use the extends keyword on a type argument

    void myFunction<T extends A>(Map<String, T> map) { ... }