how to create a new class instance object dynamically

Issue

I have a class

    class Account extends Stuff{
      String name;
      newObject(){
        return new Account();
      }
    }

inside the Stuff class I have a method

    //generates list of objects of the same type 
    //as given object and fills attribute 
    generateObjectsFromExisting(names)
      {
        List list = new List();
        InstanceMirror instanceMirror = reflect(this);
        Symbol formatSymbol = new Symbol("newObject");
        for(var name in names){
          //calles newObject function from this and returns a new object
          var newInstanceObject = instanceMirror.invoke(formatSymbol, []);
          Symbol symbol = new Symbol("name");
          InstanceMirror field = newInstanceObject.setField(symbol,name);
          list.add(newInstanceObject.reflectee)
        }
        return list;
      }

so when writing

    main(){
      var account = new Account();
      List accounts = new List();
      accounts = account.generateObjectsFromExisting(['tim','tom']);
      print(account.name) // returns null
      print(accounts[0].name) // returns tim
      print(accounts[1].name) // returns tom
    }

the problems with this way are

1 ‘generateObjectsFromExisting()’ is on the ‘account’ object and not on Account

2 I have to manually add the “newObject” Method to every single class I implement.

I would prefer a static Method like ‘Account.generateObjectsFromExisting()’
but how to to access ‘this’ (since its not available in static)
so I can say “this.new()” or something equivalent to “new Account();” eg “new this();”
and therefor be able to only have one ‘newObject’ function inside Stuff or maybe wont need it at all.

so now my code would look like this

    class Account extends Stuff{
      String name;
    }

in Stuff

    static generateObjectsFromExisting(names)
      {
        List list = new List();
        for(var name in names){
          var object = new this();
          object.name = name;
          list.add(object)
        }
        return list;
      }

in main

    main(){
      // returns list of Accounts filled with names
      accounts = Account.generateObjectsFromExisting(['tim','tom']);
      print(accounts[0].name) // returns tim
      print(accounts[1].name) // returns tom
    }

if you can show me a way to access the Class to do something like this.new(); or new this(); then obviously the class ‘Account’ needs to be accessed and not the extended ‘Stuff’

if the ‘this’ approach is not possible, then maybe you can show me a way how to access the Class from within an already existing object

like

    generateObjectsFromExisting(names)
      {
        List list = new List();
        var class = this.class;
        var newObject = class.new():
        ...          
      }

or is my current approach the only solution. .. hope not 🙂

thank you

Solution

There are two ways I can think of at the moment. But both of them are pretty close to your initial solution as they both use reflection..

The non-static solution:

class Stuff {

  generateObjectsFromExisting(List<String> names) {
    var cm = reflectClass(this.runtimeType);
    return names.map((name) {
      var newInstance = cm.newInstance(const Symbol(''), []).reflectee;
      newInstance.name = name;
      return newInstance;
    }).toList();
  }
}

The static solution:

class Stuff {

  static generateObjectsFromExisting(type, List<String> names) {
    var cm = reflectClass(type);
    return names.map((name) {
      var newInstance = cm.newInstance(const Symbol(''), []).reflectee;
      newInstance.name = name;
      return newInstance;
    }).toList();
  }
}

You would call the static solution like this:

var accounts = Stuff.generateObjectsFromExisting(Account, ['tim', 'tom']);

There might be another solution involving factory constructors but can’t think of any right now. Also, this code would easily break when you get another subclass of Stuff that does not have a name attribute. I don’t know if you really intended on putting that attribute on Account instead of Stuff.

Also answering you ‘Class’-Question. There is no class in Dart, there is only the Type and to get it you can do:

Type type1 = Account;
Type type2 = account.runtimeType;

But the Type doesn’t have any methods you could use to create a new instance.

Answered By – Dennis Kaselow

Answer Checked By – Jay B. (FlutterFixes Admin)

Leave a Reply

Your email address will not be published.