Dart pass this as a parameter in a constructor - dart

Lets say that I have an abstract class
abstract class OnClickHandler {
void doA();
void doB();
}
I have a class
class MyClass {
OnClickHandler onClickHandler;
MyClass({
this.onClickHandler
})
void someFunction() {
onClickHandler.doA();
}
}
And I have a class
class Main implements onClickHandler {
// This throws me an error
MyClass _myClass = MyClass(onClickHandler = this); // <- Invalid reference to 'this' expression
#override
void doA() {}
#override
void doB() {}
}
How can I say that use the same implementations that the Main class has? or is there an easier/better way to do this?

Your problem is that this does not yet exists since the object are still being created. The construction of Dart objects is done in two phases which can be difficult to understand.
If you change you program to the following it will work:
abstract class OnClickHandler {
void doA();
void doB();
}
class MyClass {
OnClickHandler onClickHandler;
MyClass({this.onClickHandler});
void someFunction() {
onClickHandler.doA();
}
}
class Main implements OnClickHandler {
MyClass _myClass;
Main() {
_myClass = MyClass(onClickHandler: this);
}
#override
void doA() {}
#override
void doB() {}
}
The reason is that code running inside { } in the constructor are executed after the object itself has been created but before the object has been returned from the constructor.

Related

Getting TypeLiterals via method to reduce verbosity

I want to reduce the verbosity of binding a generic interface to several implementations based on TypeLiterals...
I have an interface FieldComputer<T extends ComputeField> where ComputeField is my model interface.
Tried extending a ShortLiteral class (see example below) to reduce the verbosity but it doesn't seem to work. would like to understand why?
// A typical Guice Module
public class ConflationModule implements Module {
// typical overridden configure method
public void configure(Binder binder) {
// Works but is verbose....
bindField_1(binder,
new TypeLiteral<FieldComputer<ComputeFieldImpl>>(){},
FieldComputerImpl.class);
// Doesn't Work
bindField_1(binder,
new ShortLiteral<ComputeFieldImpl>(){},
FieldComputerImpl.class);
// Doesn't Work
bindField_2(binder,
new ShortLiteral<ComputeFieldImpl>(){},
FieldComputerImpl.class);
}
private static class ShortLiteral<CF extends ComputeField> extends TypeLiteral<FieldComputer<CF>>{}
private <CF extends ComputeField> void bindField_1(Binder binder,
TypeLiteral<FieldComputer<CF>> typeLiteral,
Class<? extends FieldComputer<CF>> clazz
) {
binder.bind(typeLiteral).to(clazz);
}
private <CF extends ComputeField> void bindField_2(Binder binder,
ShortLiteral<CF> typeLiteral,
Class<? extends FieldComputer<CF>> clazz
) {
binder.bind(typeLiteral).to(clazz);
}
}
I would suggest you just create TypeLiteral programmatically, here is an example how to do it with different implementations of one interface:
class TypeLiteralModule extends AbstractModule {
#Override
protected void configure() {
customBind(String.class, StringConsumer.class);
customBind(Integer.class, IntegerConsumer.class);
}
private <T> void customBind(Class<T> clazz, Class<? extends Consumer<T>> impl) {
var typeLiteral = (TypeLiteral<Consumer<T>>) TypeLiteral.get(Types.newParameterizedType(Consumer.class, clazz));
bind(impl).in(Singleton.class);
bind(typeLiteral).to(impl);
}
}
class StringConsumer implements Consumer<String> {
#Override
public void accept(String s) {
}
}
class IntegerConsumer implements Consumer<Integer> {
#Override
public void accept(Integer s) {
}
}

How to make override abstract method in dart or flutter

My background is from java, so i can implement abstract classes and methods in java like given bellow:
Class 1
public class Base {
public void method( VerificationCallbacks verificationCallbacks){
verificationCallbacks.signInWithEmail();
};
}
Abstract class
public abstract class VerificationCallbacks {
public abstract void signInWithEmail();
public abstract void signUpInWithEmail();
}
so we can implement these classes like
Base base = new Base();
base.method(new VerificationCallbacks() {
#Override
public void signInWithEmail() {
}
#Override
public void signUpInWithEmail() {
}
});
But now i want to implement this technique in dart or flutter
Base base = new Base();
base.method(new VerificationCallbacks());
but when i write this code to implement override methods, it shows abstract classes cannot be instantiated dart, please anyone can help me to achieve this.
class Base {
void method({
VoidCallback signInWithEmailCallback,
VoidCallback signUpWithEmailCallback,
}) {
if (true) {
signInWithEmailCallback();
} else {
signUpWithEmailCallback();
}
}
}
and
Base base = Base();
base.method(signInWithEmailCallback: () {
//
}, signUpWithEmailCallback: () {
//
});
also you can define you own alias for callback like this
typedef VerificationCallback = void Function();
and use it
class Base {
void method({
VerificationCallback signInWithEmailCallback,
VerificationCallback signUpWithEmailCallback,
}) {
// logic here
}
}

Flutter: extend a class by having to implement a method

Since I have two similar classes, but with little differences in only one function, I want to create a base class that they will extend, but that will also force them to implement that specific function. To better explain this:
class A {
void print() {print "hello";}
void func (){}
}
class B extends A {
#override func(){
//TODO
}
}
you can use an abstract base class, that is the parent of both classes
abstract class Base {
void func();
}
class A extends Base{
#override
void func() {
}
}
class B extends Base {
#override
void func() {
}
}

Jersey #Context scope

I have a hard time understanding the injection mechanism of Jersey. The JAX-RS Specification (http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-520005) states that injection via #Context is possible in Application subclasses, root resource classes and providers.
I now have a class that is instantiated at startup and has a method which is called on every request. Inside the method I need access to the current UriInfo object. The problem is, that this method is not called from my code. So I can't pass UriInfo directly to the method.
I actually want to do something like this:
public class MyClass implements ThirdPartyInterface {
// not possible because class is no Application subclass, root resource class or provider
#Context
private UriInfo uriInfo;
public void methodCallebByThirdPartyCode() {
Uri requestUri = uriInfo.getRequestUri();
// do something
}
}
I tried this. Obviously with no success:
public class MyClass implements ThirdPartyInterface {
private UriInfo uriInfo;
public MyClass(UriInfo uriInfo) {
this.uriInfo = uriInfo;
}
public void methodCallebByThirdPartyCode() {
Uri requestUri = uriInfo.getRequestUri();
// do something
}
}
#Provider
#Produces(MediaType.WILDCARD)
public class MyBodyWriter implements MessageBodyWriter<MyView> {
#Context
private UriInfo uriInfo;
private MyClass myClass;
private ThirdPartyClass thirdPartyClass;
public MyBodyWriter() {
// uriInfo is null at this time :(
myClass = new MyClass(uriInfo);
thirdPartyClass = new ThirdPartyClass();
thirdPartyClass.register(myClass);
}
public void writeTo(final MyView view, final Class<?> type, /* and so on */) throws IOException, WebApplicationException {
// execute() calls MyClass#methodCallebByThirdPartyCode()
thirdPartyClass.execute();
}
}
The only workaround I can think of is this. I don't think it's very clean:
public class MyClass implements ThirdPartyInterface {
private UriInfo uriInfo;
public void setUriInfo(final UriInfo uriInfo) {
this.uriInfo = uriInfo;
}
public void methodCallebByThirdPartyCode() {
Uri requestUri = uriInfo.getRequestUri();
// do something
}
}
#Provider
#Produces(MediaType.WILDCARD)
public class MyBodyWriter implements MessageBodyWriter<MyView> {
#Context
private UriInfo uriInfo;
private MyClass myClass;
private ThirdPartyClass thirdPartyClass;
public MyBodyWriter() {
myClass = new MyClass();
thirdPartyClass = new ThirdPartyClass();
thirdPartyClass.register(myClass);
}
public void writeTo(final MyView view, final Class<?> type, /* and so on */) throws IOException, WebApplicationException {
myClass.setUriInfo(uriInfo);
// execute() calls MyClass#methodCallebByThirdPartyCode()
thirdPartyClass.execute();
myClass.setUriInfo(null);
}
}
I hope there is a better solution, but maybe I'm completely on the wrong track.
Thanks!
Late answer, but a good question ... so lets go:
You can use a org.glassfish.hk2.api.Factory and javax.inject.Provider for injections. I don't know since which version this is available, so maybe you have to upgrade your jersery version. For the following samples i used jersey 2.12.
First you have to implement and register/bind a Factory for your MyClass:
MyClassFactory:
import javax.inject.Inject;
import javax.ws.rs.core.UriInfo;
import org.glassfish.hk2.api.Factory;
// ...
public class MyClassFactory implements Factory<MyClass> {
private final UriInfo uriInfo;
// we will bind MyClassFactory per lookup later, so
// the constructor will be called everytime we need the factory
// meaning, uriInfo is also per lookup
#Inject
public MyClassFactory(final UriInfo uriInfo) {
this.uriInfo = uriInfo;
}
#Override
public MyClass provide() {
return new MyClass(uriInfo)
}
#Override
public void dispose(UriInfo uriInfo) {
// ignore
}
}
Registration via ResourceConfig:
import org.glassfish.hk2.api.PerLookup;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
// ...
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
register(new AbstractBinder() {
#Override
protected void configure() {
bindFactory(MyClassFactory.class).to(MyClass.class).in(PerLookup.class);
// ... bind additional factories here
}
});
// ...
}
}
Now you are able to inject MyClass per lookup to providers, resources etc.
But Attention: Afaig there are two approaches and only one will work as eventually aspected for providers ...
import javax.inject.Inject;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
// ...
#Provider
#Produces("application/foo-bar")
public class MyBodyWriter implements MessageBodyWriter<MyView> {
// first approache - don't do it!
// will only injected once, cause MyBodyWriter is only instantiated once
#Inject
private MyClass myClass;
// second approache - works fine!
private final javax.inject.Provider<MyClass> provider;
// MyBodyWriter instantiate once
// get an inject provider here
#Inject
public MyBodyWriter(javax.inject.Provider<MyClass> myClassProvider) {
this.provider = myClassProvider;
}
#Override
public boolean isWriteable(Class<?> t, Type g, Annotation[] a, MediaType m) {
return t == MyView.class;
}
#Override
public long getSize(MyView t, Class<?> c, Type g, Annotation[] a, MediaType m) {
// deprecated by JAX-RS 2.0 and ignored by Jersey runtime
return 0;
}
#Override
public void writeTo(MyView v, Class<?> c, Type t, Annotation[] a, MediaType m, MultivaluedMap<String, Object> s, OutputStream o) throws IOException, WebApplicationException {
// attention: its not per lookup !!!
MyClass myClassDirectInjected = myClass;
System.out.println(myClassDirectInjected); // same instance everytime
// but this is ;)
MyClass myClassFromProvider = provider.get();
System.out.println(myClassFromProvider); // it's a new instance everytime
// ...
}
}
Hope this was somehow helpfull.

Can #ManagedPropery and #PostConstruct be placed in a base class?

I'm using a hierarchy of classes and what I would optimally try to do is have #ManagedBean's that inherit a class that have #ManagedProperty members and #PostConstruct methods.
Specifically, will this work? :
public class A {
#ManagedProperty
private C c;
#PostConstruct
public void init() {
// Do some initialization stuff
}
public C getC() {
return c;
}
public void setC(C c) {
this.c = c;
}
}
#ManagedBean
#SessionScoped
public class B extends A {
// Content...
}
Thanks in Advance!
The #ManagedProperty is inherited and will just work that way. The #PostConstruct will also be inherited, provided that the subclass itself doesn't have a #PostConstruct method. There can namely be only one. So if the subclass itself has a #PostConstruct, then the superclass' one won't be invoked.
So if you override the #PostConstruct in the subclass, then you'd need to explicitly invoke the superclass' one.
public class SuperBean {
#PostConstruct
public void init() {
// ...
}
}
#ManagedBean
public class SubBean extends SuperBean {
#PostConstruct
public void init() {
super.init();
// ...
}
}
Alternatively, provide an abstract method which the subclass must implement (without #PostConstruct!).
public class SuperBean {
#PostConstruct
public void superInit() {
// ...
init();
}
public abstract void init();
}
#ManagedBean
public class SubBean extends SuperBean {
#Override
public void init() {
// ...
}
}

Resources