Dart: instance variable override - dart

I'm confusing about the rules of class instance variable override
class S0 {
num a;
S0(this.a) {
print("in S0 :$a");
}
}
class S1 extends S0 {
num a;
S1(this.a) : super(a + 1) {
print("in S1 :$a");
}
}
main() {
var b = S1(123);
print(b.a);
}
Above is my code. I expect it prints:
in S0 :124
in S1 :123
123
But the result is:
in S0 :123
in S1 :123
123
Why? thanks!

In Dart, instance variables implicitly create getter and (for non-final members) setter functions. That is, S0's interface is implicitly:
class S0 {
num get a;
set a(num value);
S0(num a);
}
From this perspective, it should be clearer that when S0 attempts to access a, it uses its getter method, which in this case is overridden by S1 and thus always returns S1's value.
The construction order is also important. Constructing an instance of the derived S1 class would execute:
The initialization list from the derived class (S1).
The initialization list from the base class (S0).
The constructor body from the base class (S0).
The constructor body from the derived class (S1).
After step 2, the object is considered sufficiently constructed for virtual dispatch to work (i.e., for overrides in the derived class to be called). (This is unlike languages such as C++ where objects are constructed purely from base class to derived and virtual dispatch in constructors is disallowed to prevent invoking methods on unconstructed objects.)

because in the constructor body access to this (and its members) is allowed. so getter and setter is generated before execute constructor.
according to instance variable
All instance variables generate an implicit getter method. Non-final instance variables also generate an implicit setter method.
and as described in Dart Programming Language Specification Chapter 10.8.1 Inheritance and Overriding
Instance variables never override each other. The getters and setters induced by
instance variables do.
so when you call this.a in class S0 it's already overrided by child class S1;

Related

When use initializer and when use required argument

I saw these two class implementations and wonder what is the diffrence between in usage of them? and when to use each of them?
class A {
B _b;
A(B b) : _b = b;
}
class B{}
and the second variation is:
class A{
B _b;
A([B? b]) : _b = b ?? B();
}
class B{}
When you don't need an instance of class B to be created via class A you can use the B constructor in class A.
But when we want to keep the B's state we can use the required parameter in the A constructor.
In the first variation, the A class does not create an instance of the B internally. Instead, it relies on an instance of the B to be injected via the constructor.

Use of "get Stringify" and "get props" in dart

import 'package:equatable/equatable.dart';
class Point extends Equatable {
const Point(this.x, this.y);
final int x;
final int y;
#override
List<Object?> get props => [x, y];
#override
bool? get stringify => true;
Point operator +(Point other) {
return Point(x + other.x, y + other.y);
}
Point operator *(int other) {
return Point(x * other, y * other);
}
}
void main() {
print(Point(1, 1) == Point(1, 1));
print(Point(2, 1));
}
What does "Stringify" and "get props" does is this block of code?
It is given that "If set to true, the [toString] method will be overridden to output this instance's [props]." regarding the use of Stringify. What does it mean by "this instance's [props]."?
The purpose of the equatable package are described as:
A Dart package that helps to implement value based equality without needing to explicitly override == and hashCode.
To do achieve this goal, we can make our classes extend from Equatable (or use the EquatableMixin with with) which will then come with the implementation for == and hashCode.
But Equatable can't inspect the object at runtime to figure out what fields your class have defined. And Equatable does also not require a precompile step. Also, you might not want to compare all fields of your objects when determine that two objects are equal.
So the way Equatable understands what fields you want to have compared, is by using a props getter that you must define if using Equatable. This getter must then return a list of objects that should be compared when determining the equality of two objects.
Behind the scene, Equatable will call this probs getter whenever something calls == or hashCode on your object.
The purpose of the stringify getter is then to tell Equatable if it, besides == and hashCode, should also implement a toString() for your class. By default, the toString() method, in Dart, will just tell you the type of object you have like Instance of 'Point'.
If stringify returns true, then Equatable will use the returned value from probs to contruct its own toString() method which lists the value of each element in probs (which correspond to each field of your class).
It is just an extra optional service if you already want your toString() to list the value of each field of your class.

Colon : in Dart constructor syntax

class X extends Y {
X(int a, int b) : super(a,b);
}
Can someone give me an explanation about the syntax meaning of the colon :?
This feature in Dart is called "initializer list".
It allows you to initialize fields of your class, make assertions and call the super constructor.
This means that it is not the same as the constructor body. As I said, you can only initialize variables and only access static members. You cannot call any (non-static) methods.
The benefit is that you can also initialize final variables, which you cannot do in the constructor body. You also have access to all parameters that are passed to the constructor, which you do not have when initializing the parameters directly in the parentheses.
Additionally, you can use class fields on the left-hand of an assignment with the same name as a parameter on the right-hand side that refers to a parameter. Dart will automatically use the class field on the left-hand side.
Here is an example:
class X {
final int number;
X(number) : number = number ?? 0;
}
The code above assigns the parameter named number to the final field this.number if it is non-null and otherwise it assigns 0. This means that the left-hand number of the assignment actually refers to this.number. Now, you can even make an assertion that will never fail (and is redundant because of that, but I want to explain how everything works together):
class X {
final int number;
X(number): number = number ?? 0, assert(number != null);
}
Learn more.
It's ok to access non static member in initializer list.
class Point {
num x, y;
Point(this.x, this.y);
Point.origin(): this.x = 10, this.y = 10;
}
main() {
Point p = Point.origin();
print(p.x); // 10
}

Dart see if Instance of type inherits from other type

class a {/*code*/}
class b extends a {/*more code*/}
void main() {
b c = new b();
print(c.runtimeType == a); //type == inheritedType
//or
print(c.runtimeType inherits a); //operator for inheritance
//or
print(c inherits a); //other operator for inheritance
}
Can you use type == inheriting type, type inherits other type, or instance inherits other type or type?
Is there even a way to do such thing?
Because I have not found any way yet.
Use is.
You can do c is a. Notice that new a() is a is true as well. If you really want to know if an instance is a subtype of another type, you might ask c is a && c.runtimeType != a.

How are objects declared and defined in F#?

I need clarity on how objects are declared and assigned a definition in F#.
What's happening in this code?
let service = {
new IService with
member this.Translate(_) = raise error }
My guess is we're creating an object that will implement some interface on the fly even though there is no actual class that's backing this object. Hence, we're removing the ceremony involved with creating an object by not having to declare a separate class to use it. In this case, we're minimizing the ceremony involved for implementing a mock object that could be used within a unit test.
Is my understanding accurate?
I tried to research my question and found the specification for F# 3.0 (Section - 6.3.8 Object Expressions)
6.3.8 Object Expressions An expression of the following form is an object expression: { new ty0 args-expropt object-members interface
ty1 object-members1 … interface tyn object-membersn } In the case
of the interface declarations, the object-members are optional and are
considered empty if absent. Each set of object-members has the form:
with member-defns endopt Lexical filtering inserts simulated $end
tokens when lightweight syntax is used. Each member of an object
expression members can use the keyword member, override, or default.
The keyword member can be used even when overriding a member or
implementing an interface.
For example:
let obj1 =
{ new System.Collections.Generic.IComparer<int> with
member x.Compare(a,b) = compare (a % 7) (b % 7) }
You can get a pretty good picture of what is happening behind the scenes if you look at the generated IL using a decompiler like ILSpy. For the example involving IComparer, it generates a hidden class, which implements the interface:
internal sealed class obj1#2 : IComparer<int> {
public obj1#2() : this() { }
int IComparer<int>.System-Collections-Generic-IComparer(int x, int y) {
int num = x % 7;
int num2 = y % 7;
if (num < num2) { return -1; }
return (num > num2) ? 1 : 0;
}
}
Inside the body of the method, it then creates a new instance:
IComparer<int> obj1 = new obj1#2();

Resources