How to set type definitions depending on the extending class in dartlang - flutter

Is there a way to declare return types of methods or the object-prefix to be the "extendingClass" like you would do in PHP with the static::class?
So for example:
abstract class AbstractModel {
// Should return the database-provider for the given model
dynamic get modelProvider;
// Save instance to Database - Create new if no ID exists,
// else update existing
dynamic save() {
if( id == null ) {
modelProvider.insert(this);
} else {
modelProvider.update(this);
}
return this;
}
}
class ToDo extends AbstractModel {
ToDoProvider get modelProvider {
return ToDoProvider;
}
}
So in this example, obviously AbstractModel does not yet know what the return type of modelProvider will be, but I do know that it will always be the same type for a given child. Also, the return type of the save method would always be the child-class. But when writing it like this I will get an error for overwriting the modelProvider with an invalid return type.
Due to darts javascript-like nature I assume there is no way to actually achieve this like you would in PHP. But then I wonder how to type-save build re-usable code? I am trying to implement a small eloquent like query-scheme for my models so I don't have to write each CRUD method for every model - but I would still like to be precise about the types and not use dynamic everywhere.
So is there a way to do that in dart or am I completely off the track regarding dart standards?

You can use generics:
abstract class AbstractModel<ChildType extends AbstractModel<ChildType>> {
// Should return the database-provider for the given model
ModelProvider<ChildType> get modelProvider;
// Save instance to Database - Create new if no ID exists,
// else update existing
ChildType save() {
if( id == null ) {
modelProvider.insert(this);
} else {
modelProvider.update(this);
}
return this;
}
}
class Model extends AbstractModel<Model> {
}
abstract class ModelProvider<T> {
void insert(T value);
void update(T value);
}
class MyModelProvider extends ModelProvider<Model> {
...
}

Related

Declare a variable to store an object that is only constructed with a specific named constructor in dart

class ExampleClass {
//default constructor
ExampleClass() {
//do stuff
}
//named constructor
ExampleClass.namedConstructor() {
//do stuff
}
}
void main() {
//is there a way to create a variable with datatype to store an object that is constructed only with a specific constructor?
//I have tried something like this, but it returns an error
ExampleClass.namedConstructor variable_1;
}
Is there any way to do this or an alternative? because I need to be able to differentiate between an object that is constructed with the default constructor or with a named constructor.
You can add some identification to classes builded with different constructors and compare entities by unique parameters.
If instances of your classes creating once (Singleton design pattern), you can create entities as constants and compare it by reference:
const administrator = User.administrator();
class User {
final int id;
User(this.id);
factory User.administrator() {
return User(0);
}
factory User.administrator(int id) {
return User(id);
}
}

MapStruct: How to update a bean reference instead properties values

Folks,
I have the following situation with MapStruct: I want to always update a field with a new instance instead of setting values in a pre-existing instance.
Example:
class A {
     B fieldB;
}
class B {
     String fieldString;
}
class ADTO {
     BDTO fieldB;
}
class BDTO {
     String fieldString;
}
I have the following mapping with MapStruct:
void copy(ADTO aDTO, #MappingTarget A a);
The result generated is similar to:
if (aDTO.getFieldB()!= null) {
if (a.getFieldB() == null) {
a.setFieldB(new B());
}
bDTOToB(aDTO.getFieldB(), a.getFieldB());
} else {
a.setFieldB(null);
}
What I would like to generate is the following:
if (aDTO.getFieldB()!= null) {
a.setFieldB(new B()); // ALWAYS create a new B instance
bDTOToB(aDTO.getFieldB(), a.getFieldB());
} else {
a.setFieldB(null);
}
I add that I need the 2 behaviors: for some fields the current behavior suits me, that is, set the values in an existing instance. For other fields, I need this change in behavior as I mentioned before (a.setFieldB(newB())).
Is it possible to do that? What better strategy?
The only way this is possible is like this:
#BeforeMapping
default void init( #MappingTarget A a ) {
a.setFieldB( new B() );
}
void copy(ADTO aDTO, #MappingTarget A a);
The #BeforeMapping will set your field prior to check. It will however not ommit the (now obsolete) null check on the target in the generated code.
There's no way to control the target check in MapStruct. The NullValuePropertyMappingStrategy defines how a null source should be handled in the target.

Checking if build macro already processed ancestor node

Assume you have type-building macro, interface invoking #:autoBuild using aforementioned macro, class implementing the interface and class extending it. Macro will fail if the class doesn't contain specific method.
Like so:
Macro.hx
package;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
class Macro
{
macro public function build():Array<Field>
{
var fields = Context.getBuildFields();
for (field in fields) {
if (field.name == "hello") {
//Do some modifications
return fields;
}
}
Context.error('${Context.getLocalClass().toString()} doesn\'t contain a method `hello`', Context.currentPos());
return null;
}
}
I.hx
package;
#:autoBuild(Macro.build())
interface I {}
Foobar.hx
package;
class Foobar implements I
{
public function new() {}
public function hello(person:String)
{
return 'Hello $person!';
}
}
Foo.hx
package;
#:keep
class Foo extends Foobar {}
As you can see, we're checking if field "hello" exists. However, Context.getBuildFields contains only fields of current class, and build will fail for Foo.
This is where my idea comes in: Why not just check if any ancestor was already processed? We'll change Macro.hx to reflect just that:
Macro.hx
package;
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
class Macro
{
macro public function build():Array<Field>
{
var c = Context.getLocalClass().get();
if(isAncestorAlreadyProcessed(c)) {
return null;
}
var fields = Context.getBuildFields();
for (field in fields) {
if (field.name == "hello") {
//Do some modifications
c.meta.add(":processed", [], c.pos);
return fields;
}
}
Context.error('${Context.getLocalClass().toString()} doesn\'t contain a method `hello`', Context.currentPos());
return null;
}
private static function isAncestorAlreadyProcessed(c:ClassType)
{
if (c.meta.has(":processed")) return true;
if (c.superClass == null) return false;
return isAncestorAlreadyProcessed(c.superClass.t.get());
}
}
And for the main questions: Do I misunderstand haxe macro type building? Is there a more viable way of making this work? Does my code fail in specific scenarios? Are there any harmful side-effects caused by this code?
I'm trying to resolve this issue.
No, this is the way to go, use metadata to store information of the classes you processed (source).
Another way, if you don't need this information at runtime, is to use a static array on a dedicated class like here. Afterwards, you can even push this information in your compiled code, see here.
Hope that helps.

How do I mock Class<? extends List> myVar in Mockito?

I want to mock a Class in Mockito. It will then have a .newInstance() call issued which will be expected to return an actual class instance (and will return a mock in my case).
If it was setup correctly then I could do:
ArrayList myListMock = mock(ArrayList.class);
when(myVar.newInstance()).thenReturn(myListMock);
I know I can set it up so that a new instance of class ArrayList will be a mock (using PowerMockito whenNew), just wondering if there was a way to mock this kind of a class object so I don't have to override instance creation...
Below is the real class I'm trying to mock, I can't change the structure it is defined by the interface. What I'm looking for is a way to provide cvs when initialize is called.
public class InputConstraintValidator
implements ConstraintValidator<InputValidation, StringWrapper> {
Class<? extends SafeString> cvs;
public void initialize(InputValidation constraintAnnotation) {
cvs = constraintAnnotation.inputValidator();
}
public boolean isValid(StringWrapper value,
ConstraintValidatorContext context) {
SafeString instance;
try {
instance = cvs.newInstance();
} catch (InstantiationException e) {
return false;
} catch (IllegalAccessException e) {
return false;
}
}
Mockito is designed exclusively for mocking instances of objects. Under the hood, the mock method actually creates a proxy that receives calls to all non-final methods, and logs and stubs those calls as needed. There's no good way to use Mockito to replace a function on the Class object itself. This leaves you with a few options:
I don't have experience with PowerMock but it seems it's designed for mocking static methods.
In dependency-injection style, make your static factory method into a factory instance. Since it looks like you're not actually working with ArrayList, let's say your class is FooBar instead:
class FooBar {
static class Factory {
static FooBar instance;
FooBar getInstance() {
if (instance == null) {
instance = new FooBar();
}
return instance;
}
}
// ...
}
Now your class user can receive a new FooBar.Factory() parameter, which creates your real FooBar in singleton style (hopefully better and more threadsafe than my simple implementation), and you can use pure Mockito to mock the Factory. If this looks like it's a lot of boilerplate, it's because it is, but if you are thinking of switching to a DI solution like Guice you can cut down a lot of it.
Consider making a field or method package-private or protected and documenting that it's visible for testing purposes. Then you can insert a mocked instance in test code only.
public class InputConstraintValidator implements
ConstraintValidator<InputValidation, StringWrapper> {
Class<? extends SafeString> cvs;
public void initialize(InputValidation constraintAnnotation) {
cvs = constraintAnnotation.inputValidator();
}
public boolean isValid(StringWrapper value,
ConstraintValidatorContext context) {
SafeString instance;
try {
instance = getCvsInstance();
} catch (InstantiationException e) {
return false;
} catch (IllegalAccessException e) {
return false;
}
}
#VisibleForTesting protected getCvsInstance()
throws InstantiationException, IllegalAccessException {
return cvs.newInstance();
}
}
public class InputConstaintValidatorTest {
#Test public void testWithMockCvs() {
final SafeString cvs = mock(SafeString.class);
InputConstraintValidator validator = new InputConstraintValidator() {
#Override protected getCvsInstance() {
return cvs;
}
}
// test
}
}
I think you just need to introduce an additional mock for Class:
ArrayList<?> myListMock = mock(ArrayList.class);
Class<ArrayList> clazz = mock(Class.class);
when(clazz.newInstance()).thenReturn(myListMock);
Of course the trick is making sure your mocked clazz.newInstance() doesn't end up getting called all over the place because due to type-erasure you can't specify that it's actually a Class<ArrayList>.
Also, be careful defining your own mock for something as fundamental as ArrayList - generally I'd use a "real one" and populate it with mocks.

Eclipse refactor overridden method into final and abstract parts

I have a method which i'd like to refactor
Basically i want to split the top level method in a abstract and a final part.
The method in question is overridden in quite a few places where additional functionality is added, but eventualy the super call is always made.
The code now basically look like:
(not all Extending classes override but those that do, do it this way)
class Base {
public Object getStuff(String key) {
out = //code to get data from the Database.
return out
}
class Extended1 extends Base {
public Object getStuff(String key) {
if("some_non_db_value".equals(key)) {
return "some custom stuff";
}
return super.getStuff(key);
}
}
What i'd like as a result would be something like:
class Base {
public final Object getStuff(String key) {
out = getCustom(key);
if(out != null) {
return custom;
}
out = //code to get data from the Database.
return out
}
public abstract Object getCustom(String key);
}
class Extended1 extends Base {
public Object getCustom(String key) {
if("some_non_db_value".equals(key)) {
return "some custom stuff";
}
return null;
}
}
I was hoping there would be a refactor action (or partial refactor) to get to (or closer to) this point.
I would first rename getStuff() to getCustom() which would take care of all the extended classes. Then changing the Base class should be relatively easy.