I was trying to implement loose coupling in one of my Flutter projects. It was not able to find the method.
Have replicated the same in a simple Dart code, how can I fix this, and is there some way to achieve loose coupling in Dart?
abstract class A{}
class B extends A{
void help(){
print("help");
}
}
class C {
A b;
C({required this.b});
void test(){
b.help();
}
}
void main() {
var c = C(b:B());
c.test();
}
Giving error at b.help(), the method does on exist.
Exact error
The method 'help' isn't defined for the type 'A'.
b is known to be of type A, and the A interface does not provide a help method.
I don't know exactly what your definition of "loose coupling" is (it'd be better to describe a specific problem that you're trying to solve), but if you want help to be callable on type A, then you must add it to the A interface.
You alternatively could explicitly downcast b to B with a runtime check:
class C {
A b;
C({required this.b});
void test() {
// Shadow `this.b` with a local variable so that the local
// variable can be automatically type-promoted.
final b = this.b;
if (b is B) {
b.help();
}
}
}
Or if you want duck typing, you could declare (or cast) b as dynamic:
class C {
dynamic b;
C({required this.b});
void test() {
try {
b.help();
} on NoSuchMethodError {}
}
}
although I would consider the last form to be bad style.
Related
I have a class A with some properties:
abstract class A {
double doubleA;
String stringA;
...
A({this.doubleA = 0, this.stringA = ""});
}
and a class B with some properties, that extends class A:
class B extends A {
int intB;
String stringB;
B({
this.intB = 0,
this.stringB = "",
double doubleA = 0,
String stringA = "",
}) : super(doubleA: doubleA, stringA: stringA);
}
In my code I want to now check if an instance of A has a value that is of type of subclass B:
A a; // Value can be of different subtypes of A including B
if(a is B) {
// here dart should give me access to the properties of a like:
print(a.stringA);
// but it should also be possible to access the type B properties
// since the value of a can also be of subclass type B:
print(a.stringB);
}
This sounds wrong at first but I know that it can work because of examples in flutter.
Example Listener:
Listener(
onPointerSignal: (event) {
// event is of type PointerSignalEvent which has no property 'scrollDelta'.
// So print(event.scrollData); does not work here.
if (event is PointerScrollEvent) {
// if you check if event is of subtype PointerScrollEvent the property 'scrollDelta'
// that is included in the class PointerScrollEvent becomes available.
print(event.scrollDelta); // works without any problem.
}
},
}
However I have not been able to replicate this with my classes A and B and I don't know why it doesn't work. I have also looked into the implementations of these flutter classes and copied the class structure but I can still only access the properties of A after the check if(a is B) which doesn't correspond to the behavior observed with the flutter classes.
What am I doing wrong? Am I am missing something?
Thanks for reading :D <3
If you declare a variable 'a' as being of type 'A', you will not be able to access the properties of classes inheriting from A (like B).
Let's say A is Animal and B is Baboon. Baboon inherits properties from Animal, so all variables instantiated with the Baboon type with have access to properties from both classes. But variables instantiated with the Animal type will only have access to the Animal properties.
Here are some examples: https://medium.com/jay-tillu/inheritance-in-dart-bd0895883265
For example, I expect <T extends type> can works like this:
Class Parent {
String data;
Parent({ this.data });
}
Class Child extends Parent {
Child({ this.data }) : Parent(data: data);
void showData() { print(data); }
}
T wrapper<T extends Parent>(String value) {
var result = T(data: value);
return result;
}
void main() {
var trial = wrapper<Child>("Hello world");
trial.showMessage(); // print "Hello world"
}
But turns out it gives me error at var result = T(data: value);, saying that T is not a function. When I specified , I expect that T can be operated like Parent class, and if I supplied its descendant like Child, the operation done will be Child instead. But the constructor will work either way because T extends Parent. Is such thing possible?
Constructors are not inherited. You know that already, because you wrote one yourself in your child class that does nothing but call the base class with the same parameters.
One could as well write a different constructor. So "X extends Y" says a lot about X, but it does not say anything about how the constructor of X looks (or whether it even has a constructor accessible in that scope). So a constructor call is not in the properties available to you when you specify your generic to "extend Y", because Y can do exactly nothing to make sure all it's derivates follow a specific construction method.
Different languages deal with the problem of "but how do I construct a new instance of my generic type" in different ways, but the underlying concept is common to almost all concepts of generics where the generic code is compiled before knowing the specific types of all T's handled. A constructor is not inherited in most OOP languages, therefor it is not guaranteed to be there for any "X extends Y" even if Y has it.
It might be easy to overlook when you have all your code in one compilation unit. The compiler should be able to figure it out, right? But your code might not be in a single compilation unit:
Codebase one:
Class Parent {
String data;
Parent({ this.data });
}
T wrapper<T extends Parent>(String value) {
var result = T(data: value);
return result;
}
At this point, the compiler has no idea what "Child" might look like. It cannot possibly determine that the child class that will be used in the Future has a constructor like that.
Codebase 2:
Class Child extends Parent {
Child({ this.data }) : Parent(data: data);
void showData() { print(data); }
}
void main() {
var trial = wrapper<Child>("Hello world");
trial.showMessage(); // print "Hello world"
}
Now, at this point, a compiler could figure out that the program it's given would actually work. Some concepts of generics do that, where generics cannot be compiled into independent libraries, they always come as source code, because only the final compiler producing the executable can determine whether it would work with a specific class. Flutter does not do this. Flutter needs the generic itself be valid for the constraints given.
All newer language's versions of generics have followed the path of knowing the constraints beforehand and only allowing code operating inside those constraints. And I think it's good because while it has it's shortcomings, it leaves less room for errors or cryptic error messages.
I am using the flutter Mobx for state management.
I have a simple class:-
class A {
int x;
A(this.x);
}
How can I observe if x changes inside the class in another Mobx store:-
class MyStore extends _MyStore with _$MyStore {
Subs(A a) : super(a);
}
abstract class _MyStore with Store {
#observable
A a;
_Subs(this.a)
}
I want MyStore to observe the a.x.
Is it possible, if yes how?
I ran in to the same issue the other day using flutter mobx ^1.2.1+3 (dart) and
flutter_mobx ^1.1.0+2.
The first thing that comes to my mind is to annotate the field in question, I.e x with the #observable attribute. But it doesn't seem to be effective outside a store class.
So you have to observe the field using the Observable class.
To make it work your code should look something like this:
class A {
//replace with less verbose "var"
Observable<int> x = Observable(0);
A(this.x);
}
class MyStore extends _MyStore with _$MyStore {
Subs(A a) : super(a);
}
abstract class _MyStore with Store {
A a;
_Subs(this.a)
//Will be calculated whenever a change to a.x is observed.
#computed
int get xSquare => a.x.value * a.x.value;
}
As you can see I removed the observable attribute from a, since it does not need to be observed if you want to react to changes to a.x in your store. You probably noticed that you have to access the value of the observable using .value.
That should conclude how you observe a field of a class external to the store, inside your store.
I am not sure that this would be helpful since it is Javascript/Typescript, but that's what I would do :
class Foo {
#observable name = 'foo'
}
class Bar {
foo: Foo
constructor(instanceOfFoo) {
this.foo = instanceOfFoo
autorun(() => {
// Logs foo name when it changes
console.log(this.foo.name)
})
reaction(
() => this.foo.name,
() => {
// Logs foo name when it changes
console.log(this.foo.name)
}
)
}
#observable
name = 'bar'
#computed
get fooNamePlusBarName {
// recomputes automatically whenever foo or bar name changes
return this.foo.name + this.name
}
}
Basically you pass Foo instance to the Bar constructor (or just use imported singleton if it fits you), then you have 3 options: computed, reaction and autorun
I have a class in c++ that I'm wrapping into python with pybind11. That class has a std::function, and I'd like to control how the arguments to that function are dealt with (like return value policies). I just can't find the syntax or examples to do this...
class N {
public:
using CallbackType = std::function<void(const OtherClass*)>;
N(CallbackType callback): callback(callback) { }
CallbackType callback;
void doit() {
OtherClass * o = new OtherClass();
callback(o);
}
}
wrapped with
py::class_<OtherClass>(...standard stuff...);
py::class_<N>(m, "N")
.def(py::init<N::CallbackType>(),
py::arg("callback"));
I all works: I can do this in python:
def callback(o):
dosomethingwith(o)
k = N(callback)
, but I'd like to be able to control what happens when callback(o); is called - whether python then will take ownership of the wrapped o variable or not, basically.
I put a printout in the destructor of OtherClass, and as far as I can tell, it never gets called.
OK, I think I figured it out:
Instead of std::function, use a pybind11::function:
using CallbackType = pybind11::function
and then
void doit(const OtherClass &input) {
if (<I want to copy it>) {
callback(pybind11::cast(input, pybind11::return_value_policy::copy));
} else {
callback(pybind11::cast(input, pybind11::return_value_policy::reference));
}
}
I see nothing in pybind11/functional that allows you to change the ownership of the parameters at the point of call, as the struct func_wrapper used is function local, so can not be specialized. You could provide another wrapper yourself, but in the code you can't know whether the callback is a Python function or a bound C++ function (well, technically you can if that bound C++ function is bound by pybind11, but you can't know in general). If the function is C++, then changing Python ownership in the wrapper would be the wrong thing to do, as the temporary proxy may destroy the object even as its payload is stored by the C++ callback.
Do you have control over the implementation of class N? The reason is that by using std::shared_ptr all your ownership problems will automagically evaporate, regardless of whether the callback function is C++ or Python and whether it stores the argument or not. Would work like so, expanding on your example above:
#include <pybind11/pybind11.h>
#include <pybind11/functional.h>
namespace py = pybind11;
class OtherClass {};
class N {
public:
using CallbackType = std::function<void(const std::shared_ptr<OtherClass>&)>;
N(CallbackType callback): callback(callback) { }
CallbackType callback;
void doit() {
auto o = std::make_shared<OtherClass>();
callback(o);
}
};
PYBIND11_MODULE(example, m) {
py::class_<OtherClass, std::shared_ptr<OtherClass>>(m, "OtherClass");
py::class_<N>(m, "N")
.def(py::init<N::CallbackType>(), py::arg("callback"))
.def("doit", &N::doit);
}
(note: this is related to Usage preference between a struct and a class in D language but for a more specific use case)
When writing a D interface to, say, C++ code, SWIG and others do something like this:
class A{
private _A*ptr;//defined as extern(C) elsewhere
this(){ptr=_A_new();}//ditto
this(string s){ptr=_A_new(s);} //ditto
~this(){_A_delete(ptr);} //ditto
void fun(){_A_fun(ptr);}
}
Let's assume no inheritance is needed.
My question is: wouldn't it be preferable to use a struct instead of a class for this?
The pros being:
1) efficiency (stack allocation)
2) ease-of-use (no need to write new everywhere, eg: auto a=A(B(1),C(2)) vs auto a=new A(new B(1),new C(2)) )?
The cons being:
require additional field is_own to handle aliasing via postblit.
What would be the best way to do so?
Is there anything else to worry about?
Here's an attempt:
struct A{
private _A*ptr;
bool is_own;//required for postblit
static A opCall(){//cannot write this() for struct
A a;
a.ptr=_A_new();
a.is_own=true;
return a;
}
this(string s){ptr=_A_new(s); is_own=true;}
~this(){if(is_own) _A_delete(ptr);}
void fun(){_A_fun(ptr);}
this(this){//postblit;
//shallow copy: I don't want to call the C++ copy constructor (expensive or unknown semantics)
is_own=false; //to avoid _A_delete(ptr)
}
}
Note the postblit is necessary for cases when calling functions such as:
myfun(A a){}
I suggest that you read this page. The only functions on C++ classes that you can call in D are virtual functions. That means that
D cannot call C++ special member functions, and vice versa. These include constructors, destructors, conversion operators, operator overloading, and allocators.
And when you declare a C++ class in D, you use an extern(C++) interface. So, your class/struct would look like this
extern(C++) interface A
{
void fun();
}
However, you'd need another extern(C++) function to allocate any objects of type A, since it's C++ code that has to do that as the D code doesn't have access to any of the constructors. You'd also need a way to pass it back to C++ code to be deleted when you're done with it.
Now, if you want to wrap that interface in a type which is going to call the extern(C++) function to construct it and the extern(C++) function to delete it (so that you don't have to worry about doing that manually), then whether you use a class or struct depends entirely on what you're trying to do with it.
A class would be a reference type, which mirrors what the C++ class actually is. So, passing it around would work without you having to do anything special. But if you wanted a guarantee that the wrapped C++ object was freed, you'd have to do so manually, because there's no guarantee that the D class' finalizer would ever be run (and presumably, that's where you'd put the code for calling the C++ function to delete the C++ object). You'd have to either use clear (which will actually be renamed to destroy in the next release of the compiler - dmd 2.060) to destroy the D object (i.e. call its finalizer and handle the destruction of any of its member variables which are value types), or you'd have to call a function on the D object which called the C++ function to delete the C++ object. e.g.
extern(C++) interface A
{
void fun();
}
extern(C++) A createA();
extern(C++) void deleteA(A a);
class Wrapper
{
public:
this()
{
_a = createA();
}
~this()
{
deleteA(_a);
}
auto opDispatch(string name, Args...)(Args args)
{
return mixin("_a." ~ name ~ "(args)");
}
private:
A _a;
}
void main()
{
auto wrapped = new Wrapper();
//do stuff...
//current
clear(wrapped);
//starting with dmd 2.060
//destroy(wrapped);
}
But that does have the downside that if you don't call clear/destroy, and the garbage collector never collects your wrapper object, deleteA will never be called on the C++ object. That may or may not matter. It depends on whether the C++ object really needs its destructor to be called before the program terminates or whether it can just let its memory return to the OS (without its destructor being called) when the program terminates if the GC never needs to collect the wrapper object.
If you want deterministic destruction, then you need a struct. That means that you'll need to worry about making the struct into a reference type. Otherwise, if it gets copied, when one of them is destroyed, the C++ object will be deleted, and the other struct will point to garbage (which it will then try and delete when it gets destroyed). To solve that, you could use std.typecons.RefCounted. Then you get something like
extern(C++) interface A
{
void fun();
}
extern(C++) A createA();
extern(C++) void deleteA(A a);
struct Wrapper
{
public:
static Wrapper opCall()
{
Wrapper retval;
retval._a = createA();
return retval;
}
~this()
{
if(_a !is null)
{
deleteA(_a);
_a = null;
}
}
auto opDispatch(string name, Args...)(Args args)
{
return mixin("_a." ~ name ~ "(args)");
}
private:
A _a;
}
void main()
{
auto wrapped = RefCounted!Wrapper();
//do stuff...
}
You could also define the wrapper so that it has the ref-counting logic in it and avoid RefCounted, but that would definitely be more complicated.
Regardless, I would definitely advise against your suggestion of using a bool to mark whether the wrapper owns the C++ object or not, because if the original wrapper object gets destroyed before all of the copies do, then your copies will point to garbage.
Another option if you did want the C++ object's copy constructor to be used (and therefore treat the C++ object as a value type) would be to add an extern(C++) function which took the C++ object and returned a copy of it and then use it in a postblit.
extern(C++) A copyA(A a);
this(this)
{
if(_a !is null)
_a = copyA(a);
}
Hopefully that makes things clear enough.