stackunderflow
stackunderflow

Reputation: 1774

Flutter - How to instantiate an object from a Type

My aplogoze for the original question. I'm getting confused. This is my actual question.

I have a situation where I need to use some defined classes as an object of type Type and instantiate it's object instance. As for now, I'm using self defined static instantiator function to call the constructor and it's working good. So I can just call Function.apply() to create an object. Rather than doing that, is there any way I can use the class's Type to emulate the class's constructor.


What have I tried? They say to use Mirror, a solution for Dart's reflection.

import 'dart:mirrors' have failed with error

Target of URI doesn't exists

Or at least if it's not ready provided I don't know where to get the package.

import 'package:reflectable/mirrors.dart' with package from git://github.com/dart-lang/reflectable.git only defines all Mirror implemented classes, but function reflect is missing.

Upvotes: 18

Views: 18180

Answers (4)

user21506239
user21506239

Reputation:

For Dart and Flutter projects, Dart supports the keyword new for creating instances of classes but in this case we can optionally create the Task object without new keyword.

class Task {
  String text;
  bool isComplete;

  Task(this.text, [this.isComplete = false]);
}

// Create object and Providing default values for parameters
final task = Task("Do something.", true);

You can call this task object as global variable or locally inside the build method, e.g;

@override
Widget build(BuildContext context) {
  final task = Task("Do something.", true);
  ...
}

Globally;

Class MyWidget extends StatefulWidget {
   final task = Task("Do something.", true);
   const MyWidget({Key? key}) : super(key: key);

   @override
   State createState() => MyWidgetState();
}

class MyWidgetState extends State<MyWidget> {

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 80.0,
      width: double.infinity,
      color: Colors.red,
      child: Center(child: Text(widget.text)),
    );
  }
  ...
}

Upvotes: 0

Salvaterra
Salvaterra

Reputation: 41

If you don't want to user reflection, you can do this.

class A {
}
class B {
}

dynamic init(Type cls){
  switch (cls) {
    case A:
      return A();
    case B:
      return B();
  }
}

void main() {
  print(init(A));
  print(init(B));
}

As a best practice, to keep organized and avoid using dynamic, you could extend from a common base and call a static constructor.

class A extends Base{
}
class B extends Base{
}

abstract class Base{
  static Base init(Type cls){
    switch (cls){
      case A:
        return A();
      case B:
        return B();
  }}
}

void main() {
  print(Base.init(A));
  print(Base.init(B));
}

Output:

Instance of 'A'
Instance of 'B'

Process finished with exit code 0

Upvotes: 3

lrn
lrn

Reputation: 71653

You cannot create an instance of a class from a Type object representing the class, at least not without mirrors (and neither the Flutter nor the web platform supports mirrors).

You cannot tear-off a constructor (yet, I hope we'll add that feature at some point), so the option of creating a static helper function which calls the constructor, and passing the helper function around, is the best current solution.

If you know the number of arguments required by such a function, you don't need to use Function.apply, you can just call it directly.

Upvotes: 10

Xavier
Xavier

Reputation: 4005

You can tear-off a function if you don't add the parentheses (). You don't need dart:mirror.

void main() {
  // Tear off a global function
  Function myFunction = MyClass.someStaticFunction;

  // Call it statically
  myFunction('arg');

  // Call it dynamically
  Function.apply(myFunction, ['arg']);

  // Tear it off with a precise Function Type
  void Function(String) myFunction2 = MyClass.someStaticFunction;
}

class MyClass {
  static void someStaticFunction(String someArg) {
    print('someStaticFunction $someArg');
  }
}

Upvotes: 5

Related Questions