Inheritance About Mixin and Class Dart - dart

Please look the code ,i want to know
1.who is C super
2.in the class C ,when i call 'super.method()', Mixin excute 'void method()'(so C's super is Mixin?), then, when excute 'super.method()', B excute 'void method()'(so C's super is B?),why?
It's running Dart 2.1.2
void main() {
C().printSuper();
C().method();
}
abstract class A {
void method() {
print("A");
}
}
class B implements A {
#override
void method() {
print("B");
}
}
mixin Mixin on A {
#override
void method() {
super.method();
print("mixin");
}
}
class C extends B with Mixin {
void printSuper() {
super.method();
}
}
print message:
I/flutter (21340): B
I/flutter (21340): mixin
I/flutter (21340): B
I/flutter (21340): mixin
i expected the output print message:
I/flutter (21340): B
I/flutter (21340): B
I/flutter (21340): mixin

The superclass of C is B with Mixin, which is an anonymous class introduced by the extends B with Mixin clause.
The class C is equivalent to a class declared as follows:
class _BwithMixin extends B implements Mixin {
void method() {
super.method();
print("mixin");
}
}
class C extends _BwithMixin {
void printSuper() {
super.method();
}
}
So, the printSuper doesn't directly hit the method of B, it hits the method of the superclass of C which is B with Mixin, and that method is the one copied from Mixin. It will then call super.method() from _BwithMixin, and the superclass of that is B, so it will first print mixin and then B.

Related

How to use a mixin-ed method of a class in another mixin of another class

I have class B which has object of class A as a member field.
And I want to access the new mixin-ed method of class A in the mixin-ed method for class B. I tried the following but it doesn't work.
https://dartpad.dev/?id=2af929e713c46e9b853aee84f4407007&null_safety=true
class A {}
class B {
final A objOfA;
const B(this.objOfA);
}
mixin MixedA on A {
void someNewMethod() {
// do something
}
}
mixin MixedB on B {
void someMethod() {
objOfA.someNewMethod(); // <-- error
}
}
mixin MixedB on B means that classes that use MixedB are known only to derive from B. Class B provides no guarantee that its objOfA member is an instance of MixedA. Some of your options:
Make B require that objOfA is a MixedA by declaring it as: final MixedA objOfA;
If you can't unconditionally declare objOfA to be a MixedA, perhaps you could make B generic and make MixedB require a specialized base type:
class B<DerivedA extends A> {
final DerivedA objOfA;
const B(this.objOfA);
}
mixin MixedB on B<MixedA> {
// ...
}
Make MixedB perform a runtime check:
mixin MixedB on B {
void someMethod() {
final objOfA = this.objOfA;
if (objOfA is MixedA) {
objOfA.someNewMethod();
}
}
}
If you can personally guarantee that objOfA will always be a MixedA when MixedB is used (but you can't provide a static, compile-time guarantee), you could make MixedB override objOfA and cast it to a MixedB:
mixin MixedB on B {
#override
MixedA get objOfA => super.objOfA as MixedA;
void someMethod() {
objOfA.someNewMethod();
}
}

Dart any differences between with or without abstract keyword?

Hi I just would like to know if there is any difference between giving abstract keyword or not like so.
// with
abstract class A {}
class B extends A {}
// without
class A {}
class B extends A {}
Should I give it?
With abstract you can omit implementations of methods and getters/setters
// with
abstract class A {
int foo();
String get bar;
set baz(String value);
}
var a = A(); // error about instantiating abstract class
class B extends A {
// error about missing implementations
}
var b = B(); // ok
// without
class A {
int foo(); // error about missing implementation
String get bar; // error about missing implementation
set baz(String value); // error about missing implementation
}
class B extends A {}

Casting subtype fails

class A {
void hello() {
print('world');
}
}
class B extends A {
#override
void hello() {
print('StackOverflow');
}
}
(A() as B).hello(); results in type 'A' is not a subtype of type 'B' in type cast.
Full disclosure: I don't know Dart.
You can't do this kind of cast because it might result in function calls or field accesses that aren't well defined.
I'll change your example to demonstrate:
class A {
void hello() {
print('world');
}
}
class B extends A {
#override
void hello() {
print('StackOverflow');
}
void hello2() {
print('Is Great!');
}
}
Now if you do (A() as B).hello2(); what should Dart do? This isn't really obvious, so it doesn't allow you to do that. Going the other way isn't an issue since B inherits all stuff from A.
class A {
void hello() {
print('world');
}
}
class B extends A {
#override
void hello() {
print('StackOverflow');
}
}
class C extends A {
#override
void hello() {
print('Hello');
}
}
Another issue is a value that has type A may be a different subtype of A like C
The way casting works is you can only go from a more specific type, B in this case, to a more general type, A. Your creating an instance of A, but A is not B.
Dart generally allows you to down-cast from a super-type to a sub-type because the value might actually be of the sub-type.
Animal animal = Cat();
if (something) animal = Dog();
...
Cat cat = animal as Cat; // Allowed, the animal may be a cat.
However, Dart 2 disallows down-casts in a few cases where it is obvious (even to the compiler) that the cast will always fail at run-time. That's what you are hitting here: (A() as B). The A() calls a generative constructor, so the compiler knows that the type of that expressions is exactly A (and not any proper sub-type of A). So, it knows that casting that to B will always fail at run-time, and for your own protection, it disallows the program entirely. Hence, a compile-time error.

Why can Iterable<DeclarationMirror> not be cast to Iterable<MethodMirror>?

This code does not work on the Dart VM (1.22.0-dev.9.0), but does work on DartPad (unknown version):
import 'dart:mirrors';
class Thing {
Thing();
}
void g(ClassMirror c) {
var constructors = c.declarations.values
.where((d) => d is MethodMirror && d.isConstructor) as Iterable<MethodMirror>;
print(constructors);
}
void main() {
g(reflectClass(Thing));
}
Results in:
Unhandled exception:
type 'WhereIterable<DeclarationMirror>' is not a subtype of type 'Iterable<MethodMirror>' in type cast where
WhereIterable is from dart:_internal
DeclarationMirror is from dart:mirrors
Iterable is from dart:core
MethodMirror is from dart:mirrors
#0 Object._as (dart:core-patch/object_patch.dart:76)
#1 g (file:///google/src/cloud/srawlins/strong/google3/b.dart:9:55)
#2 main (file:///google/src/cloud/srawlins/strong/google3/b.dart:14:3)
#3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:261)
#4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:148)
(but in DartPad results in (MethodMirror on 'Thing').)
Note that if I hand-craft some classes that implement each other, and do the same thing, it works:
abstract class DM {
bool get t;
}
abstract class MM implements DM {
MM();
bool get t;
}
class _MM implements MM {
bool get t => true;
}
void f(Map<dynamic, DM> dms) {
var mms = dms.values.where((dm) => dm is MM && dm.t) as Iterable<MM>;
print(mms);
}
void main() {
f({1: new _MM()});
}
which nicely prints: (Instance of '_MM')
Just because the iterable returned by .where() can only contain MethodMirror instances, doesn't allow the cast. The type is propagated from c.declarations.values which is DeclarationMirror.
While you can cast a DeclarationMirror to a MethodMirror, a cast from Iterable<DeclarationMirror> to Iterable<MethodMirror> is invalid, because there is no is-a relationship between these to iterables.
It seems when built to JS by dart2js, some generic types are dropped, this is why this works in DartPad.
You can create a new List<MethodMirror> like
import 'dart:mirrors';
class Thing {
Thing();
}
void g(ClassMirror c) {
var constructors = new List<MethodMirror>.from(
c.declarations.values.where((d) => d is MethodMirror && d.isConstructor));
print(constructors);
}
void main() {
g(reflectClass(Thing));
}
There is an open issue to make this easier https://github.com/dart-lang/sdk/issues/27489

#override of Dart code

I noticed PetitParserDart has a lot of #override in the code, but I don't know how do they be checked?
I tried IDEA dart-plugin for #override, but it has no effect at all. How can we use #override with Dart?
From #override doc :
An annotation used to mark an instance member (method, field, getter or setter) as overriding an inherited class member. Tools can use this annotation to provide a warning if there is no overridden member.
So, it depends on the tool you use.
In the current Dart Editor(r24275), there's no warning for the following code but it should (it looks like a bug).
import 'package:meta/meta.dart';
class A {
m1() {}
}
class B extends A {
#override m1() {} // no warning because A has a m1()
#override m2() {} // tools should display a warning because A has no m2()
}
The #override annotation is an example of metadata. You can use Mirrors to check for these in code. Here is a simple example that checks if the m1() method in the child class has the #override annotation:
import 'package:meta/meta.dart';
import 'dart:mirrors';
class A {
m1() {}
}
class B extends A {
#override m1() {}
}
void main() {
ClassMirror classMirror = reflectClass(B);
MethodMirror methodMirror = classMirror.methods[const Symbol('m1')];
InstanceMirror instanceMirror = methodMirror.metadata.first;
print(instanceMirror.reflectee); // Instance of '_Override#0x2fa0dc31'
}
it's 2021 . the override it's optional
Use the #override annotation judiciously and only for methods where the superclass is not under the programmer's control, the superclass is in a different library or package, and it is not considered stable. In any case, the use of #override is optional. from dart api https://api.dart.dev/stable/2.10.5/dart-core/override-constant.html
example
Class A {
void say (){
print ('Say something 1') ;
}
}
Class B extends A {
#override
void adds() { // when i don't type the same name of super class function show an
// warning not an error say 'The method doesn't override an inherited
// method.' because it's not same name but when type the same name must be
// overriding
print ('Say something 2 ')
}
Update : the main use of #override is when try to reach abstract method inside abstract class in sub class that inherited to the abstract super class . must use #override to access the abstract method .

Resources