I want to call a sibling method without calling the overridden method. Seems like casting this to the base class type should work, but doesn't.
Specifically, I want to call Base.bar() from Base.foo() without calling any overrides of that method (from Subclass).
class Base {
void foo() {
print("Base.foo");
(this as Base).bar(); // I *don't* want to invoke Subclass.bar
}
void bar() {
print("Base.bar");
}
}
class Subclass extends Base {
#override
void bar() {
print("Subclass.bar");
super.bar();
}
}
x = Subclass();
x.foo();
// Expected Output
// Base.foo
// Base.bar
// Actual Output
// Base.foo
// Subclass.bar
// Base.bar
This is a kludge until a good answer is given.
class Base {
void foo() {
print("Base.foo");
// can't do this => (this as Base).bar();
Base_bar();
}
void Base_bar() {
print("Base.bar");
}
void bar() {
Base_bar();
}
}
class Subclass extends Base {
#override
void bar() {
print("Subclass.bar");
super.bar();
}
}
Try this
class Subclass extends Base {
#override
void bar() {
super.bar();
}
}
Related
In Dart we can use generic classes [class]. We can also specialize those classes [class]. However at runtime the specialization is not used. (In C++ this is called template programming)
Example: The following code will result in the output
Hallo world
How are you
class MyClass<T> {
foo( print('Hallo world'); );
}
class MyClassInt implements MyClass<int> {
#override
foo( print('How are you'); );
}
main() {
MyClass<int> a = Myclass<int>();
MyClassInt b = MyClassInt();
a.foo();
b.foo();
}
How can the specialization (here type [int]) be done, that it is called at runtime, i.e.
main() {
MyClass<int> a = Myclass<int>();
a.foo();
}
should result in the outcome "How are you".
As mentioned by jamesdlin, Dart does not support specialization. But you can do something like this to make the illusion:
class MyClass<T> {
factory MyClass() {
if (T == int) {
return MyClassInt() as MyClass<T>;
} else {
return MyClass._();
}
}
// Hidden real constructor for MyClass
MyClass._();
void foo() {
print('Hallo world');
}
}
class MyClassInt implements MyClass<int> {
#override
void foo() {
print('How are you');
}
}
void main() {
final a = MyClass<int>();
final b = MyClassInt();
final c = MyClass<String>();
a.foo(); // How are you
b.foo(); // How are you
c.foo(); // Hallo world
}
I want to understand why Dart can see that the object b in printBye() function knows it is an Instance of Bye, but it does not know how to figure out the instance variable a;
class Hello {
void world<T>(T a) {}
}
class Bye {
int a = 1;
}
class Something extends Hello {
#override
void world<T>(T a) {
printBye(a);
}
}
void printBye<T>(T b) {
print(b); // prints Instance of Bye
print(b.a); // error
}
void main() {
new Something()..world(new Bye());
}
https://dartpad.dartlang.org/527e6692846bc018f929db7aea1af583
Edit: here's a simplified version of the code that achieves the same effect:
class Bye {
int a = 1;
}
void printBye<T>(T b) {
print(b); // prints Instance of Bye
print(b.a); // error
}
void main() {
printBye(new Bye());
}
Here's a simple way to look at it: you did call printBye with a Bye, but you could have called it with any other type. When you call printBye with an int, that int wont have a .a. Therefore, you have to assume that printBye could be called with anything. Object represents that anything as every class derives from it.
If you are sure that it will be called with a Bye or a subclass, you can do this to get rid of the error:
class Bye {
int a = 1;
}
void printBye<T extends Bye>(T b) {
print(b); // prints Instance of Bye
print(b.a); // not an error anymore
}
void main() {
printBye(new Bye());
}
More info: https://dart.dev/guides/language/language-tour#restricting-the-parameterized-type
In Swift 4, I used to do something like this to locally store objects of variable classes:
class Repo {
var mediaType : MyBaseClass.Type
func doSomething() {
mediaType.someStaticMethod();
}
}
class SpecificClass : MyBaseClass {
static func someStaticMethod() -> void {
// Stuff
}
}
repo = Repo(SpecificClass.self)
repo.doSomething(); // Executes `Stuff`
Moving to Dart 2, this is the closest I've gotten, yet the error specified at the bottom is blocking me.
class Repo {
Type mediaType;
void doSomething() {
mediaType.someStaticMethod();
}
}
class SpecificClass extends MyBaseClass {
static void someStaticMethod() {
// Whatever
}
}
repo = Repo(SpecificClass)
repo.doSomething() // Should execute `Whatever`, but for the error
Which generates this error:
The method 'someStaticMethod' isn't defined for the class 'Type'
Is this sort of trick feasible with Dart 2?
Is there way to overriding method in Dart like JAVA, for example:
public class A {
public void handleLoad() {
}
}
And when overriding:
A a = new A() {
#Override
public void handleLoad() {
// do some code
}
};
No, Dart does not have anonymous classes. You have to create a class that extends A and instantiate it.
No but it much less useful in Dart because you can just reassign function:
typedef void PrintMsg(msg);
class Printer {
PrintMsg foo = (m) => print(m);
}
main() {
Printer p = new Printer()
..foo('Hello') // Hello
..foo = ((String msg) => print(msg.toUpperCase()))
..foo('Hello'); //HELLO
}
However you will need some extra boilerplate to access instance.
Use type Function:
class A {
final Function h
A(this.h);
void handleLoad(String loadResult) { h(loadResult); }
}
Or
class A {
final Function handleLoad;
A(this.handleLoad);
}
A a = new A((String loadResult){
//do smth.
});
I am a little bit confused: can I override a setter / getter but still use the super setter/getter? If yes - how?
Use case:
class A {
void set value(num a) {
// do something smart here
}
}
class B extends A {
void set value(num a) {
// call parent setter and then do something even smarter
}
}
If this is not possible how can one still preserve the API but expand the logic in the new class. The users of the code already use instance.value = ... so I do not want to change it to method call is possible.
Please help:)
You can access to parent with super. :
class B extends A {
void set value(num a) {
super.value = a;
}
}
Only need call super.value = a
class A {
void set value(String value) {
print(value.toUpperCase());
}
}
class B extends A {
void set value(String value) {
super.value = value;
print(value.toLowerCase());
}
}
void main() {
B b = new B();
b.value = "Hello World";
}