I have a class that takes one of its subclasses as an argument. When constructing that subclass, I want to be able to use this as the value of that argument:
class A(val b: B)
class B extends A(this)
However, this fails to compile
this can be used only in a class, object, or template
[error] class B extends A(this)
[error] ^
Is there any way to get around this? I'm pretty sure that a pattern like this can be written in Java.
I'm not so sure about the last statement:
public class MyClass {
static class A {
A(B b) {
System.out.println(b.value);
}
}
static class B extends A {
String value;;
B() {
super(this);
value = "x";
}
}
public static void main(String args[]) {
new B();
}
}
gives the following error:
/MyClass.java:10: error: cannot reference this before supertype constructor has been called
super(this);
^
There is no good reason to attempt to let the this reference escape the scope of the constructor before the object itself has been constructed. Refactor it.
Related
abstract class Ainterface {
String? name;
List<Binterface?>? list;
}
abstract class Binterface {
String? age;
int? len;
}
class ObjA extends Ainterface {
String? name;
List<ObjB?>? list;
ObjA({this.name, this.list});
}
class ObjB extends Binterface {
String? age;
int? len;
ObjB({this.age, this.len});
}
I used objb as the type of each item in the list, but the editor gave an error 'obja. List =' ('void function (list < objb? >?)) isn't a valid override of 'Ainterface.list=' ('void Function(List<Binterface?>?)').
How I can solve this problem?
Fields (data members) in Dart implicitly provide getters and setters as part of the interface. Therefore when you write:
abstract class Ainterface {
List<Binterface?>? list;
}
The interface is implicitly:
abstract class Ainterface {
List<Binterface?>? get list;
set list(List<Binterface?>? value);
}
The problem is that your derived class wants to provide an interface:
class ObjA extends Ainterface {
List<ObjB?>? get list;
set list(List<ObjB?>? value);
}
Even though List<ObjB?>? is substitutable for List<Binterface?>?, the reverse is not true: List<Binterface?>? is not substitutable for List<ObjB?>?, and that's the direction that matters for the setter.
The list setter in ObjA is not a safe override of the corresponding setter from Ainterface because it would allow callers to violate its contract. Ainterface.list advertises that it allows being set to any instance of a Binterface, but ObjA.list expects only an instance of ObjB. As a concrete example, if the override were allowed, then the following code would compile without error:
class AnotherB extends Binterface {}
void main() {
Ainterface a = ObjA();
a.list = [AnotherB()]; // This error would not be caught at compile-time.
}
And now a.list contains a List<AnotherB> even though ObjA.list expects List<ObjB>, and you'd eventually get an error at runtime if you try to use a.list as a List<ObjB>.
If you can logically guarantee that the above scenario will never happen, then you can use the covariant keyword to relax static type-checking and allow the override:
abstract class Ainterface {
covariant List<Binterface?>? list;
}
but I re-emphasize that the above code removes some type-safety. By using the covariant keyword, you take responsibility for ensuring that you do not violate the contract in practice.
Alternatively:
Reconsider if your abstract base class needs to expose setters as part of its interface, and expose only getters if possible.
Make Ainterface a generic class parameterized on the concrete type of Binterface:
abstract class Ainterface<DerivedB extends Binterface> {
List<DerivedB?>? list;
}
class ObjA extends Ainterface<ObjB> {
List<ObjB?>? list;
}
I'll also point out that overriding fields is usually a bad idea, and you usually should be explicitly overriding getters and setters anyway.
In the Ainterface abstract class you declared that a list should be declared of type Binterface so any class extending that class should do that. so when you want to declare a class extending this class you should consider that. if you want to also declare a list from type ObjB you can do it after that. it will be like this:
class ObjA extends Ainterface {
String? name;
List<Binterface?>? list;
List<ObjB ?>? list2;
ObjA({this.name, this.list, this.list2});
}
I'm trying to create an abstract class called SpanishData
And then I want to create another class called alphabet that extends Spanish data
I'm getting an error: the superclass SpanishData doesn't have a zero-argument constructor. How do I fix this?
Here is my code:
abstract class SpanishData{
String englishWord;
String spanishWord;
String mp3;
SpanishData(this.englishWord,this.spanishWord,this.mp3);
void getList (){
}
}
//the alphabet class
import '../SpanishDataAbstract.dart';
class Alphabet extends SpanishData{
#override
void getList(
)
}
You need to refer to the properties of the parent class your class is extending. You can do this using the super keyword.
The super() method on a class constructor allows a subclass to pass arguments and execute the constructor of its superclass.
The code below works:
abstract class SpanishData{
String englishWord;
String spanishWord;
String mp3;
SpanishData(this.englishWord,this.spanishWord,this.mp3);
void getList (){
}
}
class Alphabet extends SpanishData{
// create a constructor of the alphabet class and call the parent constructor
Alphabet(String englishWord, String spanishWord, String mp3) : super(englishWord, spanishWord, mp3);
#override
void getList(){}
}
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.
I'm having some trouble with deriving a pointer to a derived class. I think it has something to do with a constructor. Do I have to create a new constructor in my derived class? How to I create a pointer from a derived class? Thanks
Class Base
{
public:
int myfunction(int a,int b,int c)
{
return a+b+c;
}
};
Class Derived: public Base
{
int newfunction(int a, int b, int c)
{
return a*b*c;
};
};
int main()
{
// this doesn't work at all.. I get all errors every time I try to refer to the object
//instantiated from my derived class.
//I know it's my lack of understanding.
Derived *NewObject = new Derived;
//Why wont this work?
}
C++ is case sensitive, and the keyword class is lowercase. You wrote Class for both classes, and it looks like it's the only issue with your code.
I want to get access to an argument in a private constructor without using mutable variables:
class Class1 {
val strArgPublic = // get strArg argument from the private constructor. How?
private def this(strArg: String) = {
//.....
}
}
I want not only get strArg and return it, but change it a little bit and return a new modified copy of it.
How can I do this?
There is not only private constructor in your class. There is also a public constructor. You should decide what will be a value of strArgPublic after public constructor. If there is should be no public constructor you should define your class like this:
class Class1 private(strArg: String) {
val strArgPublic = transform(strArg)
}
If there should be a parameterless public constructor you could define one as auxiliary constructor:
class Class1 private(strArg: String) {
val strArgPublic = transform(strArg)
def this() = this("default")
}