How Inheritance works with mixins in dart - dart

I have the following code:
class A {
void m() {
print("hello");
}
}
mixin B {
void m() {
print("mixin class b");
}
}
class C extends A with B {
void m() {
print("m of c");
super.m();
}
}
void main() {
C cc = C();
cc.m();
}
Here when I write super.m() it is referring to the mixin class rather than m() of class A, why? Which exactly is its superclass referenced by super.
How can I then call m() of class A from C?

I don't think it is possible to get the m method on A in your example. The reason is by using mixins you are telling the compiler you want to extend A but please insert all methods from B even if one of the methods overrides an existing one. So after compile, the compiled class of C ends up not even containing A.m.
There are some details about this behavior in this older article and with some explanation about why this is the case: https://medium.com/flutter-community/https-medium-com-shubhamhackzz-dart-for-flutter-mixins-in-dart-f8bb10a3d341

Related

How to call a second ancestor method in Dart

Is it possible to call a second ancestor method in dart? something like super.super.hello()? If it's possible, how can it be written?
class A {
void hello() {
print('A');
}
}
class B extends A {
#override
void hello() {
print('B');
}
}
class C extends B {
#override
void hello() {
// How to call the hello() implemented in the class A here?
}
}
void main() {
var c = C();
c.hello();
}
It's not possible.
The reason it's not possible is that it breaks abstraction.
When you look at class C extend B, all you need to know about B is which signatures its members has and which interfaces it implements. As long as that stays effectively the same, your valid code will keep working.
Consider what would happen if the author of B decided to make themselves a helper base-class:
abstract class _BaseB extends A {
String get _myName;
#override
void hello() {
print(_myName);
}
}
class B extends _BaseB {
#override
String get _myName => "B";
}
That's a perfectly valid refactoring. The resulting class B has all the same members and implements all the same interfaces (and also _BaseB, but it's private so nobody can see that).
The C class above would keep working if all it does is to call super.hello(). If it had a way to ask for super.super.hello(), that might no longer be valid.
Similarly if the B class was changed to:
class B implements A {
#override
void hello() {
print("B");
}
}
(changing extends to implements), then all methods of B works the same as before and it implements the same interfaces. Again, there is no visible differences to the users of the B class.
But if you could call something like A.super.hello() to reach the A class's hello method, then that would now break because that method isn't in the B class at all.
So, by restricting super.hello() to only call methods on the precise class you write as the superclass, you are prevented from introducing dependencies on the implementation of B, dependencies which would make otherwise valid refactorings into breaking changes.

Dart forcing me to implement non abstract method in child class

I am trying abstract classes I found one issue that I have to implement the non-abstract method having a body in child classes
code:
abstract class Animal{
void breathe(); //abstract method
void makeNoise(){
//non abstract method
print('making animal noises!');
}
}
abstract class IsFunny{
void makePeopleLaugh();//abstract method
}
class TVShow implements IsFunny{
String name;
#override
void makePeopleLaugh() {
// TODO: implement makePeopleLaugh
print("TV show is funny and make people laugh");
}
}
class Comedian extends Person implements IsFunny{
Comedian(String name, String nation) : super(name, nation);
#override
void makePeopleLaugh() {
// TODO: implement makePeopleLaugh
print('make people laugh');
}
}
class Person implements Animal{
String name,nation;
Person(this.name,this.nation);
//we must implement all the methods present in Abstract class and child should override the abstract methods
#override
void breathe() {
// TODO: implement breathe
print('person breathing through nostrils!');
}
//there should be no compulsion to override non abstract method
#override
void makeNoise() {
// TODO: implement makeNoise
print('shouting!');
}
}
void main(List arguments) {
var swapnil=new Person('swapnil','India');
swapnil.makeNoise();
swapnil.breathe();
print('${swapnil.name},${swapnil.nation}');
}
here I am trying not to implement makeNoise method in my Person class but it gives error and says abstract method must be implemented.
Is this bug or I am getting concept wrong
You are using implements, which is used for interfaces, not for inheritance. The keyword you are looking for is extends.
abstract class Foo {
void doThing() {
print("I did a thing");
}
void doAnotherThing();
}
class Bar extends Foo {
#override
void doAnotherThing() {
print("I did another thing");
}
}
I don't believe this is a bug. The method is still in an abstract class that you are implementing. I think that you instead intended to extend the class in which case you would call super.makeNoise() in the override.
I figured out the solution after some time I understood that when inheriting abstract class I should have used extends keyword instead of implements due to which dart was telling me to also implement the non-abstract method as it is compulsory to implement all methods when using interfaces.
I think my question was silly

How to capture the generic type of a generic constraint?

Consider the following generic class:
class Foo<T extends Bar<dynamic>> {}
How can I obtain the generic argument of Bar at compile time?
I would expect the following code to print int, but it prints dynamic:
class Bar<T> {}
class Foo<T extends Bar<dynamic>> {
Foo(this.value) {
_debugBarType(value);
}
final T value;
void _debugBarType<A>(Bar<A> value) {
print(A);
}
}
void main() {
Foo<Bar<int>>(Bar());
}
I know I could do:
class Foo<A, Bar<A>> {}
But I would like to define the Foo class using a single generic parameter instead of two.
This is currently not possible to do on any class.
There's currently a pending feature request on Dart to support such use-case: https://github.com/dart-lang/language/issues/620
It's worth noting that there's a workaround if you can add a method on the class concerned.
For example, say you have a generic class Model<T>:
class Model<T> {
T value;
}
Then you can add a "capture" method as such:
class Model<T> {
T value;
R capture<T>(void cb<P>(P value)) => cb<T>(value);
}
This then allows you to write:
void someFunction<T extends Model<dynamic>>(T model) {
model.capture(<P>(value) {
// `P` will be the captured type instead of `dynamic`
});
}

In Dart, how do I get code completion when using noSuchMethod?

I'd like to use noSuchMethod to reduce boilerplate when writing a lot of similar methods. But then the API is worse for my library's users because code completion no longer works. I tried this but I get warnings about unimplemented methods:
class ThingMixin {
foo();
bar();
noSuchMethod(Invocation inv) {
...
}
}
Is there a workaround?
The trick is to define the API in a separate class:
abstract class ThingApi {
foo();
bar();
}
class ThingMixin implements ThingApi {
noSuchMethod(Invocation inv) {
...
}
}
(Note that noSuchMethod cannot call super if you want it to work as a mixin.)

Dart, never allow nested Generics?

I would like to use the nested Generics, like
class Class<List<T>> {
...
}
But always Dart Editor gives me alerts. How should I avoid these alerts?
Well, Dart Editor is right. This code doesn't make any sense. Without further information on what you are trying to do (don't hesitate to update your question), I am assuming you actually mean one of those:
class MyClass<T> {
List<T> listField;
// other stuff
}
Or maybe the list itself should be generic?
void main() {
MyClass<SomeCustomListClass<String>> instance = new MyClass();
}
class MyClass<T extends List<String>> {
T listField;
// ...
}
Or maybe everything has to be generic:
void main() {
MyClass<String, SomeCustomListClass<String>> instance = new MyClass();
}
class MyClass<TElement, TList extends List<TElement>> {
TList listField;
TElement _firstListElement;
// whatever that could be used for
}

Resources