Method that accepts an instance of the concrete class - dart

I have an abstract class Filter that is implemented by various transaction filters (e.g. DateFilter, AccountFilter, etc)
abstract class TransactionFilter {
String asString();
bool operator >(TransactionFilter other);
}
// Concrete implementations
class DateFilter implements TransactionFilter {
DateTime startDate, endDate;
DateFilter(this.startDate, this.endDate);
// ⏹ ERROR
// 'DateFilter.>' ('bool Function(DateFilter)') isn't a valid override of
// 'TransactionFilter.>' ('bool Function(TransactionFilter)')
bool operator >(DateFilter other) =>
startDate.isBefore(other.startDate) && endDate.isAfter(other.endDate);
}
class AccountFilter implements TransactionFilter {
List<int> accounts;
DateFilter(this.accounts);
// Same error as above
bool operator >(AccountFilter other) =>
other.any((e) => !accounts.contains(e))
}
This seems to be because Dart doesn't consider DateFilter and AccountFilter to be equivalent to TransactionFilter.
EDIT: I'd like the > operator to strictly be used by classes of the same subtype (e.g. comparing two DateFilter instances). How do I do this in the given example?

What you are doing does not make type-safe sense. Your TransactionFilter specifies that all classes that inherit from TransactionFilter do have a > operator which can compare against any object of the type TransactionFilter.
So when you in a subclass define the operator as:
bool operator >(DateFilter other)
Or:
bool operator >(AccountFilter other)
This is not allowed since DateFilter and AccountFilter is more restrictive than TransactionFilter (your DateFilter class are only allowed to compare against another DateFilter and not e.g. AccountFilter).
Update
Here is an example of how to do it instead using generics:
abstract class TransactionFilter<T extends TransactionFilter<T>> {
String asString();
bool operator >(T other);
}
// Concrete implementations
class DateFilter implements TransactionFilter<DateFilter> {
DateTime startDate, endDate;
DateFilter(this.startDate, this.endDate);
bool operator >(DateFilter other) =>
startDate.isBefore(other.startDate) && endDate.isAfter(other.endDate);
#override
String asString() {
// TODO: implement asString
throw UnimplementedError();
}
}
class AccountFilter implements TransactionFilter<AccountFilter> {
List<int> accounts;
AccountFilter(this.accounts);
bool operator >(AccountFilter other) =>
other.accounts.any((e) => !accounts.contains(e));
#override
String asString() {
// TODO: implement asString
throw UnimplementedError();
}
}

Related

Dart abstract static method

I want to create an abstract Sort class for my class project using dart which I will extend with Sorting algorithm classes like MergeSort, QuickSort, Heap, etc. I wrote the below code but I cannot create an abstract static sort method which I can override and use like
Heap.sort(arr)
OR
MergeSort.sort(arr)
Do anyone know why I cannot create abstract static method and also if you have any other way of doing this please feel free to guide me :D
abstract class Sort {
// void sort(List array);
static void sort(List array);
bool isSorted(List array) {
for (int i = 0; array.length > i - 1; i++) {
if (array[i] > array[i + 1]) {
return false;
}
}
return true;
}
void swap(arr, i, j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
As the answer linked above says, you can't have abstract static methods.
An abstract method does just one thing, it adds a method signature to the interface of the class, which other (non-abstract) classes implementing the interface then has to provide an implementation for. The abstract method doesn't add implementation.
Static methods are not part of the interface, so being abstract and static means it has no effect at all. It's a method with no implementation, which nobody can ever implement. So you're not allowed to do that.
To actually have separate classes representing different sorting algorithms, just do that directly using instance methods. That's the strategy object pattern.
abstract class Sorter<T> {
void sort(List<T> values);
int compare(T value1, T value2);
void swap(List<T> values, int index1, int index2) {
T tmp = values[index1];
values[index1] = values[index2];
values[index2] = tmp;
}
}
abstract class HeapSort<T> extends Sorter<T> {
void sort(List<T> values) {
// heap sort algorithm.
}
}
abstract class MergeSort<T> extends Sorter<T> {
void sort(List<T> values) {
// merge sort algorithm.
}
}
mixin ComparableSorter<T extends Comparable<T>> on Sorter<T> {
int compare(T value1, T value2) => value1.compareTo(value2);
}
class ComparableHeapSort<T extends Comparable<T>>
extends HeapSort<T> with ComparableSorter<T> {}
class CustomCompareHeapSort<T> extends HeapSort<T> {
int Function(T, T) _compare;
CustomCompareHeapSort(int Function(T, T) compare) : _compare = compare;
int compare(T value1, T value2) => _compare(value1, value2);
}
There are plenty of options about how to slice the API and abstract over different parts of it.
I recommend figuring out what use-cases you want to support, before starting the API design.

Enum equalization with other classes

I've created a class that only takes Enums as parameters. I figured I could create a third Enum where I would manually put every option so they have a better naming.
The only thing is, I can't test if both my third Enum instance and my class instance with the same parameters are equal just by using the == operator. Tried using equatable and considering the Enum instance as my class instance since it does implement it, but nothing works. Of course, I could create a test where all my given parameters are equal, but I just wondered whether I could do something so they return true when using the == operator.
E.g.:
Configuration
enum A {
a,
b;
}
enum B {
c,
d;
}
class Class with EquatableMixin {
const EveryDayOfYear({required this.aValue, required this.bValue});
final A aValue;
final B bValue;
#override
List<Object?> get props => [aValue, bValue];
}
enum C {
ac(Class(aValue: A.a, bValue: B.c)),
ad(Class(aValue: A.a, bValue: B.d)),
bc(Class(aValue: A.b, bValue: B.c)),
bd(Class(aValue: A.b, bValue: B.d));
const C(this._handler);
final Class _handler;
#override
A get aValue => _handler.aValue;
#override
B get bValue => _handler.bValue;
#override
List<Object?> get props => [aValue, bValue];
}
Objective
final instance = Class(aValue: A.a, bValue: B.c);
instance == C.ac; // I would like something so this operation returns true.
As commented by #Levi-Lesches here the answer to my problem was to override my operator ==:
#override
// ignore: hash_and_equals, already implemented by EquatableMixin
bool operator ==(Object other) {
return (super == other) ||
((other is Class) &&
(week == other.aValue) &&
(day == other.bValue));
}
This solved my problem and is fair since my class instance is not an Enum, but my enum constant is actually my class instance.

Google Cloud Dataflow Custom Keys with common functionality

We are using the Dataflow Java SDK and we have an increasing number of custom key classes that are almost the same.
I would like to have them extend a common abstract class however the Dataflow SDK seems to try to instantiate the abstract class causing an InstantiationException.
Caused by: java.lang.RuntimeException: java.lang.InstantiationException
at org.apache.avro.specific.SpecificData.newInstance(SpecificData.java:316)
at org.apache.avro.specific.SpecificData.newRecord(SpecificData.java:332)
at org.apache.avro.generic.GenericDatumReader.readRecord(GenericDatumReader.java:173)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:151)
at org.apache.avro.generic.GenericDatumReader.read(GenericDatumReader.java:142)
at com.google.cloud.dataflow.sdk.coders.AvroCoder.decode(AvroCoder.java:242)
at com.google.cloud.dataflow.sdk.coders.KvCoder.decode(KvCoder.java:97)
at com.google.cloud.dataflow.sdk.coders.KvCoder.decode(KvCoder.java:42)
at com.google.cloud.dataflow.sdk.util.CoderUtils.decodeFromSafeStream(CoderUtils.java:156)
at com.google.cloud.dataflow.sdk.util.CoderUtils.decodeFromByteArray(CoderUtils.java:139)
at com.google.cloud.dataflow.sdk.util.CoderUtils.decodeFromByteArray(CoderUtils.java:133)
at com.google.cloud.dataflow.sdk.util.MutationDetectors$CodedValueMutationDetector.<init>(MutationDetectors.java:108)
at com.google.cloud.dataflow.sdk.util.MutationDetectors.forValueWithCoder(MutationDetectors.java:45)
at com.google.cloud.dataflow.sdk.transforms.ParDo$ImmutabilityCheckingOutputManager.output(ParDo.java:1218)
at com.google.cloud.dataflow.sdk.util.DoFnRunner$DoFnContext.outputWindowedValue(DoFnRunner.java:329)
at com.google.cloud.dataflow.sdk.util.DoFnRunner$DoFnProcessContext.output(DoFnRunner.java:483)
at com.telstra.cdf.rmr.model.pardos.ParDoAbstractCampaignUAKeyExtractor.processElement(ParDoAbstractCampaignUAKeyExtractor.java:5
here is our abstract class,
#DefaultCoder(AvroCoder.class)
public abstract class SuperClassKey {
public SuperClassKey(){}
public abstract double getSomeValue();
}
and this is the sub class
#DefaultCoder(AvroCoder.class)
public class SubClassKey extends SuperClassKey {
public String foo;
public SubClassKey() {
}
public SubClassKey(String foo){
this.foo = foo;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SubClassKey that = (SubClassKey) o;
if (!foo.equals(that.foo)) return false;
return true;
}
#Override
public int hashCode() {
return foo.hashCode();
}
#Override
public double getSomeValue() {
return foo;
}
}
I have also tried using an interface without success.
Is it possible to have a common abstract class or interface between Keys?
The issue is likely from using a PCollection<SuperClassKey> instead of PCollection<SubClassKey>. The PCollection needs to be typed with a concrete class. The coder can be explicitly specified with .setCoder(AvroCoder.of(SubClassKey.class)) if type inference is not sufficient.
In my canse, i changed the Coder class, example:
Before:
AvroIO.parseGenericRecords(RecordConverter::convert)
.withCoder(AvroCoder.of(Struct.class)).from(...)
After:
AvroIO.parseGenericRecords(RecordConverter::convert)
.withCoder(SerializableCoder.of(Struct.class)).from(...)

Dependency Injection of Primitive Types (Decided at Runtime) With HK2

So basically, I have a situation where I want to inject primitive types into a class (i.e. a String and an Integer). You can think of a URL and port number for an application as example inputs. I have three components:
Now say I have a class, which does take in these params:
public class PrimitiveParamsDIExample {
private String a;
private Integer b;
public PrimitiveParamsDIExample(String a, Integer b) {
this.a = a;
this.b = b;
}
}
So my question here is simple. How do I inject a and b into class PrimitiveParamsDIExample?
In general, this is also asking how to inject parameters that are decided on runtime as well. If I have a and b above, read from STDIN or from an input file, they're obviously going to be different from run to run.
All the more, how do I do the above within the HK2 framework?
EDIT[02/23/15]: #jwells131313, I tried your idea, but I'm getting the following error (this one for the String param; similar one for int):
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=String,parent=PrimitiveParamsDIExample,qualifiers
I set up classes exactly as you did in your answer. I also overrode the toString() method to print both variables a and b in PrimitiveParamsDIExample. Then, I added the following in my Hk2Module class:
public class Hk2Module extends AbstractBinder {
private Properties properties;
public Hk2Module(Properties properties){
this.properties = properties;
}
#Override
protected void configure() {
bindFactory(StringAFactory.class).to(String.class).in(RequestScoped.class);
bindFactory(IntegerBFactory.class).to(Integer.class).in(RequestScoped.class);
bind(PrimitiveParamsDIExample.class).to(PrimitiveParamsDIExample.class).in(Singleton.class);
}
}
So now, I created a test class as follows:
#RunWith(JUnit4.class)
public class TestPrimitiveParamsDIExample extends Hk2Setup {
private PrimitiveParamsDIExample example;
#Before
public void setup() throws IOException {
super.setupHk2();
//example = new PrimitiveParamsDIExample();
example = serviceLocator.getService(PrimitiveParamsDIExample.class);
}
#Test
public void testPrimitiveParamsDI() {
System.out.println(example.toString());
}
}
where, Hk2Setup is as follows:
public class Hk2Setup extends TestCase{
// the name of the resource containing the default configuration properties
private static final String DEFAULT_PROPERTIES = "defaults.properties";
protected Properties config = null;
protected ServiceLocator serviceLocator;
public void setupHk2() throws IOException{
config = new Properties();
Reader defaults = Resources.asCharSource(Resources.getResource(DEFAULT_PROPERTIES), Charsets.UTF_8).openBufferedStream();
load(config, defaults);
ApplicationHandler handler = new ApplicationHandler(new MyMainApplication(config));
final ServiceLocator locator = handler.getServiceLocator();
serviceLocator = locator;
}
private static void load(Properties p, Reader r) throws IOException {
try {
p.load(r);
} finally {
Closeables.close(r, false);
}
}
}
So somewhere, the wiring is messed up for me to get an UnsatisfiedDependencyException. What have I not correctly wired up?
Thanks!
There are two ways to do this, but one isn't documented yet (though it is available... I guess I need to work on documentation again...)
I'll go through the first way here.
Basically, you can use the HK2 Factory.
Generally when you start producing Strings and ints and long and scalars like this you qualify them, so lets start with two qualifiers:
#Retention(RUNTIME)
#Target( { TYPE, METHOD, FIELD, PARAMETER })
#javax.inject.Qualifier
public #interface A {}
and
#Retention(RUNTIME)
#Target( { TYPE, METHOD, FIELD, PARAMETER })
#javax.inject.Qualifier
public #interface B {}
then write your factories:
#Singleton // or whatever scope you want
public class StringAFactory implements Factory<String> {
#PerLookup // or whatever scope, maybe this checks the timestamp?
#A // Your qualifier
public String provide() {
// Write your code to get your value...
return whatever;
}
public void dispose(String instance) {
// Probably do nothing...
}
}
and for the Integer:
#Singleton // or whatever scope you want
public class IntegerBFactory implements Factory<Integer> {
#PerLookup // or whatever scope, maybe this checks the timestamp?
#B // Your qualifier
public Integer provide() {
// Write your code to get your value...
return whatever;
}
public void dispose(String instance) {
// Probably do nothing...
}
}
Now lets re-do your original class to accept these values:
public class PrimitiveParamsDIExample {
private String a;
private int b;
#Inject
public PrimitiveParamsDIExample(#A String a, #B int b) {
this.a = a;
this.b = b;
}
}
Note I changed Integer to int, well... just because I can. You can also just use field injection or method injection in the same way. Here is field injection, method injection is an exercise for the reader:
public class PrimitiveParamsDIExample {
#Inject #A
private String a;
#Inject #B
private int b;
public PrimitiveParamsDIExample() {
}
}
There are several ways to bind factories.
In a binder: bindFactory
Using automatic class analysis: addClasses
An EDSL outside a binder: buildFactory

How to make a factory constructor that returns as const value

Is it possibly to return a different implementation of as const?
abstract class Foo<T> {
factory Foo(T thing) => const FooImpl(thing); // <= Arguments of a constant creation must be constant expressions
T get thing;
}
class FooImpl<T> implements Foo<T>{
final T thing;
const FooImpl(this.thing);
}
Dart has a delegating factory constructor to allow this
abstract class Foo<T> {
const factory Foo(T thing) = FooImpl;
T get thing;
}
class FooImpl<T> implements Foo<T>{
final T thing;
const FooImpl(this.thing);
}
see also
https://groups.google.com/a/dartlang.org/forum/#!topic/misc/cvjjgrwIHbU and
https://groups.google.com/a/dartlang.org/forum/#!topic/misc/cvjjgrwIHbU

Resources