Home > OS >  How to override toMap method from extends class
How to override toMap method from extends class

Time:09-22

I have a class B extends class A, and it have the toJson method override the class A's toJson method. But when i force class B to class A, the toJson method not be changed from class B to class A.

class A {
  String str1;

  A(this.str1);

  Map<String, dynamic> toMap() => {
    'str1': str1,
  }
}

class B extends A {
  String str2;

  B(this.str2, str1) : super(str1);

  Map<String, dynamic> toMap() => {
        'str2': str2,
        'str1': str1,
  }
}


void test(A a) {
  print(a.toMap());
}

// When I pass class B in class A parameter, it still use the class B.toMap method.
B b = B('str2', 'str1');
test(b);

CodePudding user response:

All Dart instance methods are virtual, also known has having dynamic dispatch. That means that when you call a.toMap(), which toMap implementation gets called depends on the runtime type of the object a, not the static type of the expression a.

So, in this case, you are calling toMap on an instance of B, so you use B's toMap.

This is a fairly common behavior in object oriented languages (dynamic dispatch is one of the hallmark features of object orientation: The object determines how to respond to the message you send it, here the request to do a "toMap" operation.)

Some object oriented languages also have non-virtual methods. Dart does not. You can either define a static method:

class A {
  static Map<String, dynamic> toMap(A value) => ...;
}
class B {
  static Map<String, dynamic> toMap(B value) => ...;
}

and then choose which one to call:

  print(A.toMap(a));

or you can use extension methods (which are really just static methods with a nicer call syntax) because they dispatch based on the static type of the receiver:

extension AToMap on A {
  Map<String, dynamic> toMap() => ...;
}
extension BToMap on B {
  Map<String, dynamic> toMap() => ...;
}

and call it normally:

  print(a.toMap()); // Chooses AToMap.toMap based on static type of `a`.

In most situations, if you really want to access both A.toMap and B.toMap on an instance of B, you're better of renaming one of the methods to avoid the naming conflict.

  •  Tags:  
  • dart
  • Related