How can I call super inside constructor body? - flutter

class Foo {
Foo(int y);
}
class Bar extends Foo {
int value;
Bar(int x) { // error in this line
value = x;
print("Hi there");
super(x); // error in this line
}
}
How can I call super inside constructor body?
Note:
I know I can use initialiser list to solve it but I would like to know how to call super inside method body?
Bar(int x): value = x, super(x); // works but I am not looking for it.

Dart does not support inheriting the constructors as explicitly callable methods. The initializer list you mentioned is the supported way to call unnamed super constructors in Dart.
However, you can achieve what you want with the help of named constructors. Take a look at the below example -
class Foo {
int superValue;
Foo(); //A default zero-argument constructor
Foo._init(this.superValue); //Named constructor
void initValue(int x) => Foo._init(x);
}
class Bar extends Foo {
int value;
Bar(int x) {
value = x;
print("Hi there");
super.initValue(x);
}
}
void main() {
Foo foo = Bar(10); //prints 'Hi there'
}
Hope it helps!
UPDATE
You can also call the super constructor and add other statements to the child constructor using this way -
class Foo {
int superValue;
Foo(this.superValue);
}
class Bar extends Foo {
int value;
Bar(int x) : super(x) {
value = x;
print("Hi there");
}
}
void main() {
Foo foo = Bar(10);
}

Related

How to get the parameter type of the class method with macro?

How to get the parameter type of the class method with macro?
class A{
public function new(){
//this how get method out arg[0] Type with macro?
var arg0IsInt:Bool=arg0IsInt(out);
}
public function out(a:Int){ return true; }
macro public function arg0IsInt(e:Expr):Bool{
}
}
I'm going to call a method that has a parameter for a type when I construct a letter.
You can pass out to the expression macro and then use Context.typeof() on it. The result will be a function type (TFun) whose first argument you can inspect using pattern matching.
Here's a working example:
import haxe.macro.Context;
import haxe.macro.Expr;
class Main {
static function main() {
new Main();
}
public function new() {
trace(arg0IsInt(out)); // true
trace(arg0IsInt(out2)); // false
}
public function out(a:Int) {}
public function out2(a:Float) {}
macro static function arg0IsInt(func:Expr):Expr {
return switch Context.typeof(func) {
case TFun(args, _):
switch args[0].t {
case TAbstract(_.get() => t, _) if (t.name == "Int" && t.pack.length == 0):
macro true;
case _:
macro false;
}
case _:
throw 'argument should be a function';
}
}
}
Int is a an abstract, and to make sure it's not just some random abstract that happens to be named Int in some other package, we check that it's in the toplevel package (pack.length == 0).
In fact you can go very far with pattern matching:
import haxe.macro.Context;
import haxe.macro.Expr;
class Test {
static function main() {
new Test();
}
public function new() {
trace(arg0IsInt(out)); // true
trace(arg0IsInt(out2)); // false
}
public function out(a:Int) {}
public function out2(a:Float) {}
macro static function arg0IsInt(func:Expr):Expr {
return switch Context.typeof(func) {
case TFun(_[0] => {t: TAbstract(_.get() => {name: 'Int', pack: []}, _)}, _): macro true;
case TFun(_): macro false;
case _: throw 'argument should be a function';
}
}
}

Setting setter of an interface in class implementing it

Just begin with using kotlin in android-
I am trying to use setter of an interface in a class implementing it-
interface MyInterface {
val prop: Int // abstract
var propertyWithImplementation: String
get() = "foo"
set(text){"$text foo"}
fun foo() {
print(prop)
}
}
class Child : MyInterface {
override val prop: Int = 29
override var propertyWithImplementation="bhu"
}
fun main(args: Array<String>) {
println(Child().propertyWithImplementation)
}
Output:bhu
Expected Output=bhu foo
Where am i going wrong?
You are overriding the var, not setting it, and not using the parent setter in the override, so it ends up not being used in any way. Setting it would look like e.g.
class Child : MyInterface {
override val prop: Int = 29
init {
propertyWithImplementation="bhu"
}
}
but if you do that the output will be foo because that's what the getter always returns. And the setter doesn't actually set anything, it just creates a string and ignores it.
You don't have backing fields in an interface, so you'll need to store the value somewhere else, e.g.
interface MyInterface {
protected var backingProperty: String
var propertyWithImplementation: String
get() = backingProperty
set(text){ backingProperty = "$text foo" }
}
class Child {
override var backingProperty = "foo"
}
to fix this problem.

Get type of an object in a Haxe macro

I would like to get the class of an object in a macro so that I can access its static variables:
// autoBuild macro adds static field "id_ : Int" to all subclasses
class Base {
}
class Child1 extends Base {
public function new() {}
}
class Child2 extends Base {
public function new() {}
}
class Container {
public function addChild(index: Int, object: Base) {}
macro function add(object: ???) {
// find out class of on object
// ???
// var id = class.id_;
this.addChild(id, object);
}
}
Desired usage:
var c = new Container();
c.add(new Child1());
c.add(new Child2());
You can use Context.typeof() to get the expression's type - then you need to do a bit of pattern matching to find out the type's name. The following only works with classes because it only matches TInst, but could be extended:
import haxe.macro.Context;
import haxe.macro.Expr;
class Container {
// [...]
public macro function add(self:Expr, object:Expr):Expr {
var name = switch (Context.typeof(object)) {
case TInst(_.get() => t, _): t.name;
case _: throw "object type not found";
}
return macro $self.addChild($i{name}.id_, $object);
}
}
This will generate the following code:
var c = new Container();
c.addChild(Child1.id_, new Child1());
c.addChild(Child2.id_, new Child2());
Note that accessing _id via it's unqualified name is only safe if it's actually imported (or toplevel) - in practice you'd want to use t.pack in combination with $p{} to generate the fully qualified path.

Get abstract underlying type in a build macro?

For example i have an abstract type of Bool
abstract ABool(Bool) from Bool to Bool {}
And i have a field of that type
var abool:ABool;
What i need is to know ABool underlying type (Bool) in my build macro.
#if macro
import haxe.macro.Expr;
import haxe.macro.*;
#end
class Builder {
macro static public function build():Array<Field> {
var fields = Context.getBuildFields();
for (f in fields) {
switch (f.kind) {
// looks at class variables and properties
case FVar(t, e) | FProp(_, _, t, e):
// t is a haxe.macro.ComplexType,
// lets convert it to a haxe.macro.Type,
// such that we can check if it is an abstract type or not
var type = Context.typeof(macro {var a:$t; a;});
switch (type) {
case TAbstract(t, params):
var underlyingType = t.get().type;
trace(underlyingType); //TAbstract(Bool,[])
case _:
// ignore things that are not of abstract type
}
case _:
// ignore methods
}
}
return fields;
}
}
abstract ABool(Bool) from Bool to Bool {}
#if !macro
#:build(Builder.build())
#end
class Test {
var abool:ABool;
static function main() {
}
}

Calling member functions of immutable classes

immutable class Foo
{
void bar()
{
}
}
void main()
{
auto x = new Foo();
x.bar();
// Error: function test.Foo.bar () immutable is not callable
// using argument types ()
}
What do I have to change in the program so that x.bar() compiles? Does x have the wrong type?
Looks like a bug. x is inferred to have the type Foo, which although is an immutable class, it is treated as if a mutable variable, which caused x.bar() to fail because bar() is an immutable method.
A workaround is to provide an empty immutable constructor function,
immutable class Foo
{
void bar()
{
}
immutable this() {} // <---
}
which caused the new Foo() expression to return an immutable(Foo).