I use generics in java usually with interface. I want to use generics like java. what should I do. I think use dynamic can not solve my issues.
You could do something like this:
/// To make an interface in Dart you can create an abstract class.
///
/// Then you can define a generic type with <T>.
///
/// In this sample I'm using <T extends Object> to ensure
/// that I'm not passing a nullable type (such as String?).
abstract class MyInterface<T extends Object> {
T get myValue;
}
/// Then you can implement your interface like this.
class MyInterfaceImplementation implements MyInterface<String> {
#override
final String myValue;
MyInterfaceImplementation(this.myValue);
}
Try the full code on DartPad
Related
For abstract classes is there difference between implements and extends? Which one should I use? In Java for interfaces you would use implements, but I see dart doesn't have interfaces and both implements/extends work. If I want to declare abstract class for my api methods, should I use implements or extends?
void main() {
User user = new User();
user.printName();
}
abstract class Profile {
String printName();
}
class User extends Profile {
#override
String printName() {
print("I work!!");
return "Test";
}
}
All classes in Dart can be used as interfaces. A class being abstract means you cannot make an instance of the class since some of its members might not be implemented.
extends means you take whatever a class already have of code and you are then building a class on top of this. So if you don't override a method, you get the method from the class you extends from. You can only extend from one class.
implements means you want to just take the interface of class but come with your own implementation of all members. So your class ends up being compatible with another class but does not come with any of the other class's implementation. You can implement multiple classes.
A third options, which you did not mention, is mixin which allow us to take the implementation of multiple mixin defined classes and put them into our own class. You can read more about them here: https://dart.dev/guides/language/language-tour#adding-features-to-a-class-mixins
I want to declare, but not define a factory constructor in an abstract class.
In my case, I want to create a method that accepts any class that implements a String toJson() method as well as a fromJson(Map<String, dynamic> data) factory constructor.
Is there any way to achieve that in Dart?
I'm looking for something like the following, which is not valid Dart code:
abstract class JsonSerializable {
factory fromJson(Map<String, dynamic> data);
String toJson();
}
I'm afraid that it doesn't work the way you want it to.
Constructors are not part of an interface. They act more like static members.
So, you can't add a factory to the interface, and code wouldn't have any way to call the factory constructor given a type variable extending this type anyway.
So, since constructors cannot be part of interfaces, constructors also cannot be abstract. Being abstract simply means "make the member part of the interface, but no implementation is added to class".
You can declare the factory as a normal method, but then you would only be able to call it when you already have an instance, which likely isn't what you want with a constructor.
The only way to pass code around is as functions or objects with methods. So, if you want to parameterize something by a type which is JsonSerializable, and you want to be able to create such an object, you need to pass a factory function along:
T deserialize<T extends JsonSerializable>(
String json,
T factory(Map<String, dynamic> data),
) {
return factory(jsonDecode(json) as Map<String, dynamic>);
}
You an then call it with:
var myValue = deserialize(jsonString, (x) => MyClass.fromJson(x));
(If MyClass.fromJson had been a static function instead of a constructor, you could just write deserialize(jsonString, MyClass.fromJson), but Dart doesn't yet have constructor tear-offs).
As suggested in the accepted answer, I ended up creating a Serializer<T> type that got implemented by a serializer for each class:
Turns out, this has several benefits over just having toJson/fromJson on the classes directly:
It decouples the serialization logic from the actual classes. That means better code readability because classes only contain methods that relate directly to the class — serializers can even be put into their own files.
Currently, extensions can't create constructors. So having serializers separately makes it possible to write serializers for existing classes, like String or Flutter's Color, where you can't just add a fromColor constructor.
Both these points combined mean it also works well with code generation — the classes are hand-written and the serializer can be generated in a separate file.
Code example:
class Fruit {
Fruit(this.name, this.color);
final String name;
final String color;
}
// in another file
class FruitSerializer extends Serializer<Fruit> {
Map<String, dynamic> toJson(Fruit fruit) {
return ...;
}
Fruit fromJson(Map<String, dynamic> data) {
return Fruit(...);
}
}
An then also pass the serializer to the code that needs it:
someMethod<T>(Serializer<T> serializer, T value) {
...
}
someMethod(FruitSerializer(), someFruit);
final fruit = recreateFruit(FruitSerializer());
Obviously, you can't pass an object that can't be serialized to the code, because the method expects a Serializer<T>.
Say I have two JdbcTemplates, one for "employee_database" and one for "customer_database". Say a class EmployeeDAO requires the former as a constructor dependency, and CustomerDAO requires the latter. If I were writing these classes myself, I'd do
public class EmployeeDAO {
public EmployeeDAO(#Named("employee") JdbcTemplate employeeJdbcTemplate)
and
bind(JdbcTemplate.class).annotatedWith(Names.named("employee")).toInstance(employeeJdbcTemplateInstance);
And likewise for CustomerDAO
But I can't modify EmployeeDAO to add the Named annotation to the constructor parameters.
What's the canonical way to insure the DAO objects get their respective JdbcTemplates in this scenario without having to instantiate them myself?
In a sense, this is similar to the "robot legs problem", as you're trying to create similar-but-slightly-different trees of objects. In the eponymous problem, you're using a reusable Leg object that receives a #Left Foot and a #Right Foot as needed; in this problem, you're similarly varying the binding of an inner object (JdbcTemplate) based on an outer object's (DAO's) context.
A "cheap way" is to use #Provides methods, which is a particularly low-cost solution if your consumer DAOs have few dependencies and are unlikely to change frequently. Naturally, creating a full Provider would also work too, but this syntax works just fine for most cases.
public class YourModule extends AbstractModule {
#Override public void configure() {}
#Provides EmployeeDao createEmployeeDao( // Name doesn't matter.
#Named("employeeJdbcTemplate") JdbcTemplate employeeTemplate,
Dep2 dep2,
Provider<Dep3> dep3Provider) {
return new EmployeeDao(employeeTemplate, dep2, dep3Provider);
}
}
If the dep list is long, deps change frequently, or multiple classes depend on a JdbcTemplate, then private modules may be the way to go.
install(new PrivateModule() {
#Override public void configure() {
bind(JdbcTemplate.class).toInstance(employeeJdbcTemplate);
expose(EmployeeDao.class);
}
});
The example above uses an anonymous inner class, but you could also create a named class (either top-level or nested) that accepts a JdbcTemplate instance and a DAO class literal, and call it like so:
install(new DaoModule(employeeTemplate, EmployeeDao.class));
install(new DaoModule(customerTemplate, CustomerDao.class));
I have written a list() method for retrieving a list of domain class instances matching a set of filters, and this method is used for different domain classes ; the code is exactly the same except the class on which the GORM methods are called :
Store => Store.createCriteria()
Client => Client.createCriteria()
and so on.
To avoid code duplication, I have tried to make a generic version of the list method, by creating a generic class :
class QueryUtils<T> {
def list(params) {
T.createCriteria()
[...]
}
}
This way, each of my services (StoreService, ClientService, etc) can extend QueryUtils :
class StoreService extends QueryUtils<Store>
class ClientService extends QueryUtils<ClientService>
and so on, and inherit the list() method corresponding to its domain class type.
The problem is that during the execution, it doesn't work since the effective type of T is java.lang.Object, instead of the domain class type I have specified :
groovy.lang.MissingMethodException: No signature of method: static java.lang.Object.createCriteria() is applicable for argument types: () values: []
Do you know how to solve this problem?
I did something like this a while back for Hibernate (outside of Grails) - https://burtbeckwith.com/blog/?p=21
But it doesn't work with Groovy since the compiler ignores generics. But you could change it to take the class in the constructor instead of as a generic type:
class QueryUtils {
private final Class clazz
QueryUtils(Class clazz) {
this.clazz = clazz
}
def list(params) {
clazz.createCriteria()
[...]
}
}
I understand how the implementation of dynamic binding works and also the difference between static and dynamic binding, I am just having trouble wrapping my brain around the definition of dynamic binding. Basically other than it is a run-time binding type.
Basically, dynamic binding means that the address for a function call is not hard-coded into the code segment of your program when it's translated into assembly language, and is instead obtained from elsewhere, i.e. stack variables, array lookups, etc.
At a higher level, if you have a line of code:
foo(bar) //Calls a funciton
If it can be known at compile time exactly what function this will call, this is static binding. If foo could mean multiple functions depending on things not knowable at compile time, this is dynamic binding.
I understand it being evident in polymorphism. Typically when creating multiple classes that derive from a base class. If each one of the derived classes contains a function that each one uses. The base class can be used to execute a function of the derived classs and it will be properly call the correct function.
For example:
class Animal
{
void talk();
}
class Dog extends Animal
{
public void talk() { System.out.println("woof"); }
}
class Cat extends Animal
{
public void talk() { System.out.println("meow"); }
}
....
Animal zoo[2];
zoo[0] = new Dog();
zoo[1] = new Cat();
for(Animal animalToggle: zoo)
{
animalToggle.talk();
}
will print:
woof
meow
My interpretation hopefully it helps.