I want to create a new object of given type inside of generic in Vala language.
class MyClass <T> : GLib.Object
{
protected T data;
public MyClass ()
{
data = new T ();
}
}
I understand that this can't work, but what is the way to do something like that?
You are probably best instantiating it when calling the constructor for MyClass:
void main () {
new MyClass<Test> (new Test ());
new MyClass<Example> (new Example ());
}
class MyClass <T>
{
protected T data;
public MyClass (T data)
{
this.data = data;
}
}
class Test {}
class Example {}
Vala generics do not currently provide constraints. If you are going to pass in a dependency in this way you may want to consider using an interface type instead of a generic type.
Update
If you are wanting to implement a factory then an interface with a static method or function is probably best:
void main () {
var a = CommandFactory.get_command ("A");
var b = CommandFactory.get_command ("B");
a.run ();
b.run ();
}
namespace CommandFactory {
Command get_command (string criteria) {
Command result = null;
switch (criteria) {
case "A":
result = new CommandA ();
break;
case "B":
result = new CommandB ();
break;
default:
assert_not_reached ();
}
return result;
}
}
interface Command:Object {
public abstract void run ();
}
class CommandA:Object, Command {
void run () { print ("A\n"); }
}
class CommandB:Object, Command {
void run () { print ("B\n"); }
}
I assume by 'abstract fabric pattern' you mean 'abstract factory pattern'? You could try using GType introspection to then instantiate the Object, but it must be a GObject and you by pass Vala's static analysis checks:
void main () {
new MyClass<Example> (new Example ());
/* These will fail at runtime
new MyClass<string> ("this will fail at runtime");
new MyClass<ThisWillFailAtRuntime> (new ThisWillFailAtRuntime ());
*/
}
class MyClass <T>
{
protected T data;
public MyClass (T data)
{
assert (typeof(T).is_object());
this.data = Object.new (typeof(T));
}
}
class Example:Object {}
class ThisWillFailAtRuntime {}
Note that Object.new() is also a static method.
I'm not sure what you are trying to achieve, but you are probably better looking more closely at interfaces and favouring composition over inheritance in your object data model.
For example:
Production.cpp
int func1()
{
return 7;
}
void func2()
{
printf("func2");
}
void productionCode()
{
int x = func1();
if(x==7) func2();
}
TestProduction.cpp
int func1()
{
return mock().actualCall("func1").
returnIntValue();
}
void setExpFunc1(int x)
{
mock().expectOneCall("func1")
andReturnValue(x);
}
TEST(testGroupSample, testMockFunc1)
{
setExpFunc1(8);
// this will call mock func1()
productionCode();
}
TEST(testGroupSample, testRealFunc2)
{
// this will call real func1()
productionCode();
}
From my understanding, when func1() was mocked, there's no way to test the actual function.
Below sample code is just an idea on what I'm trying to do.
Because I have to test many functions that calls many functions inside.
Sometimes, I don't care on the actual result of those other function so I mocked it, but when I want to test the behavior of the real function when calling inside a function that I'm testing, I cannot do it since that function is already mocked.
Also I hope I can do this without modifying the production code, only the tests code.
No. You mocked using the linker, so, for the whole file context, the real functions do not exist.
You may achieve this by using function pointers (or std::function, …) to set the implementation used by productionCode() at runtime.
Pseudocode
int func1() { /* Production }
int func1_mock() { /* Mock */ }
std::function<int()> impl; // Use a function ptr for C
void productionCode()
{
int x = impl(); // Call current implementation
// ...
}
TEST(...)
{
impl = func1; // Use production code
productionCode();
impl = func1_mock; // Use mock instead
productionCode();
}
Is there way to overriding method in Dart like JAVA, for example:
public class A {
public void handleLoad() {
}
}
And when overriding:
A a = new A() {
#Override
public void handleLoad() {
// do some code
}
};
No, Dart does not have anonymous classes. You have to create a class that extends A and instantiate it.
No but it much less useful in Dart because you can just reassign function:
typedef void PrintMsg(msg);
class Printer {
PrintMsg foo = (m) => print(m);
}
main() {
Printer p = new Printer()
..foo('Hello') // Hello
..foo = ((String msg) => print(msg.toUpperCase()))
..foo('Hello'); //HELLO
}
However you will need some extra boilerplate to access instance.
Use type Function:
class A {
final Function h
A(this.h);
void handleLoad(String loadResult) { h(loadResult); }
}
Or
class A {
final Function handleLoad;
A(this.handleLoad);
}
A a = new A((String loadResult){
//do smth.
});
I was wondering if is possible to create an instance of a generic type in Dart. In other languages like Java you could work around this using reflection, but I'm not sure if this is possible in Dart.
I have this class:
class GenericController <T extends RequestHandler> {
void processRequest() {
T t = new T(); // ERROR
}
}
I tried mezonis approach with the Activator and it works. But it is an expensive approach as it uses mirrors, which requires you to use "mirrorsUsed" if you don't want to have a 2-4MB js file.
This morning I had the idea to use a generic typedef as generator and thus get rid of reflection:
You define a method type like this: (Add params if necessary)
typedef S ItemCreator<S>();
or even better:
typedef ItemCreator<S> = S Function();
Then in the class that needs to create the new instances:
class PagedListData<T>{
...
ItemCreator<T> creator;
PagedListData(ItemCreator<T> this.creator) {
}
void performMagic() {
T item = creator();
...
}
}
Then you can instantiate the PagedList like this:
PagedListData<UserListItem> users
= new PagedListData<UserListItem>(()=> new UserListItem());
You don't lose the advantage of using generic because at declaration time you need to provide the target class anyway, so defining the creator method doesn't hurt.
You can use similar code:
import "dart:mirrors";
void main() {
var controller = new GenericController<Foo>();
controller.processRequest();
}
class GenericController<T extends RequestHandler> {
void processRequest() {
//T t = new T();
T t = Activator.createInstance(T);
t.tellAboutHimself();
}
}
class Foo extends RequestHandler {
void tellAboutHimself() {
print("Hello, I am 'Foo'");
}
}
abstract class RequestHandler {
void tellAboutHimself();
}
class Activator {
static createInstance(Type type, [Symbol constructor, List
arguments, Map<Symbol, dynamic> namedArguments]) {
if (type == null) {
throw new ArgumentError("type: $type");
}
if (constructor == null) {
constructor = const Symbol("");
}
if (arguments == null) {
arguments = const [];
}
var typeMirror = reflectType(type);
if (typeMirror is ClassMirror) {
return typeMirror.newInstance(constructor, arguments,
namedArguments).reflectee;
} else {
throw new ArgumentError("Cannot create the instance of the type '$type'.");
}
}
}
I don't know if this is still useful to anyone. But I have found an easy workaround. In the function you want to initialize the type T, pass an extra argument of type T Function(). This function should return an instance of T. Now whenever you want to create object of T, call the function.
class foo<T> {
void foo(T Function() creator) {
final t = creator();
// use t
}
}
P.S. inspired by Patrick's answer
2022 answer
Just came across this problem and found out that although instantiating using T() is still not possible, you can get the constructor of an object easier with SomeClass.new in dart>=2.15.
So what you could do is:
class MyClass<T> {
final T Function() creator;
MyClass(this.creator);
T getGenericInstance() {
return creator();
}
}
and when using it:
final myClass = MyClass<SomeOtherClass>(SomeOtherClass.new)
Nothing different but looks cleaner imo.
Here's my work around for this sad limitation
class RequestHandler {
static final _constructors = {
RequestHandler: () => RequestHandler(),
RequestHandler2: () => RequestHandler2(),
};
static RequestHandler create(Type type) {
return _constructors[type]();
}
}
class RequestHandler2 extends RequestHandler {}
class GenericController<T extends RequestHandler> {
void processRequest() {
//T t = new T(); // ERROR
T t = RequestHandler.create(T);
}
}
test() {
final controller = GenericController<RequestHandler2>();
controller.processRequest();
}
Sorry but as far as I know, a type parameter cannot be used to name a constructor in an instance creation expression in Dart.
Working with FLutter
typedef S ItemCreator<S>();
mixin SharedExtension<T> {
T getSPData(ItemCreator<T> creator) async {
return creator();
}
}
Abc a = sharedObj.getSPData(()=> Abc());
P.S. inspired by Patrick
simple like that.
import 'dart:mirrors';
void main(List<String> args) {
final a = A<B>();
final b1 = a.getInstance();
final b2 = a.getInstance();
print('${b1.value}|${b1.text}|${b1.hashCode}');
print('${b2.value}|${b2.text}|${b2.hashCode}');
}
class A<T extends B> {
static int count = 0;
T getInstance() {
return reflectClass(T).newInstance(
Symbol(''),
['Text ${++count}'],
{Symbol('value'): count},
).reflectee;
}
}
class B {
final int value;
final String text;
B(this.text, {required this.value});
}
Inspired by Patrick's answer, this is the factory I ended up with.
class ServiceFactory<T> {
static final Map<Type, dynamic> _cache = <String, dynamic>{};
static T getInstance<T>(T Function() creator) {
String typeName = T.toString();
return _cache.putIfAbsent(typeName, () => creator());
}
}
Then I would use it like this.
final authClient = ServiceFactory.getInstance<AuthenticationClient>(() => AuthenticationClient());
Warning: Erik made a very good point in the comment below that the same type name can exist in multiple packages and that will cause issues. As much as I dislike to force the user to pass in a string key (that way it's the consumer's responsibility to ensuring the uniqueness of the type name), that might be the only way.
I got this Dart Script below and I want to access the methods from the class hello_world by JavaScript after I compiled the Dart Script with dart2js.
Does anybody know how this works?!
I already know how to access the functions like foo(...), thats not the problem, but it does not work the same way with classes and methods.
And the tutorials on dartlang.org only explain how to access functions, not methods and classes.
I dont get it...
import 'dart:js' as js;
class hello_world {
String hello = 'Hello World!';
String getHello() {
print("getHello!!!!!");
return hello;
}
void ausgabe() {
print("Hallo Welt");
//return 0;
}
}
String foo(int n) {
print("hallo");
void foo2() {
print("hallo2");
}
//works
js.context['foo2'] = foo2;
return 'Hallo';
}
void main() {
int zahl1 = 3;
int zahl2 = 1234;
String w = 'test';
hello_world test = new hello_world();
//works
js.context['foo'] = foo;
}
Assuming you want to create a Js function bind on a Dart method you can do almost the same thing :
void main() {
hello_world test = new hello_world();
// define a 'getHelloOnTest' Js function
js.context['getHelloOnTest'] = test.getHello;
}
Now on Js side you can use :
getHelloOnTest();