как динамически создать новый объект экземпляра класса

у меня есть класс

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

внутри класса Stuff у меня есть метод

    //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;
      }

поэтому при написании

    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
    }

проблемы с этим способом

1 'generateObjectsFromExisting()' находится в объекте учетной записи, а не в учетной записи

2 Мне приходится вручную добавлять метод "newObject" в каждый класс, который я реализую.

Я бы предпочел статический метод, такой как «Account.generateObjectsFromExisting()», но как получить доступ к «этому» (поскольку он недоступен в статике), поэтому я могу сказать «this.new()» или что-то эквивалентное «новой учетной записи()» ;" например, "новый это();" и поэтому иметь возможность иметь только одну функцию «newObject» внутри Stuff или, возможно, вообще не нуждаться в ней.

так что теперь мой код будет выглядеть так

    class Account extends Stuff{
      String name;
    }

в материале

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

в основном

    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
    }

если вы можете показать мне способ доступа к классу, чтобы сделать что-то вроде this.new(); или новое это(); тогда, очевидно, необходимо получить доступ к классу «Учетная запись», а не к расширенному «Материалу».

если «этот» подход невозможен, то, возможно, вы можете показать мне способ доступа к классу из уже существующего объекта

подобно

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

или мой текущий подход - единственное решение. .. надеюсь нет :)

Спасибо


person H.R.    schedule 12.11.2013    source источник


Ответы (1)


Есть два способа, о которых я могу думать на данный момент. Но оба они довольно близки к вашему первоначальному решению, поскольку оба используют отражение.

Нестатическое решение:

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();
  }
}

Статическое решение:

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();
  }
}

Вы бы назвали статическое решение следующим образом:

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

Может быть другое решение, связанное с фабричными конструкторами, но сейчас я не могу придумать ни одного. Кроме того, этот код легко сломается, если вы получите другой подкласс Stuff, не имеющий атрибута name. Я не знаю, действительно ли вы намеревались поместить этот атрибут в Account вместо Stuff.

Также отвечая на ваш вопрос «Класс». В Dart нет класса, есть только Type и чтобы его получить можно сделать:

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

Но у Type нет никаких методов, которые вы могли бы использовать для создания нового экземпляра.

person Dennis Kaselow    schedule 12.11.2013
comment
атрибут «имя» был просто примером;) в моем реальном случае я устанавливал их динамически. классный ReflectClass (тип); отвечает на несколько моих вопросов :D обычно я без колебаний просматриваю API. Итак, внутри вашего/статического метода есть способ получить тип Stuff, не передавая его, или лучше есть эквивалент этому? - person H.R.; 13.11.2013
comment
Поскольку он статичен, и вы не хотите передавать какую-либо ссылку на тип (и вы сказали, что хотите тип Stuff), вы можете просто передать тип Stuff в reflectClass, например var cm = reflectClass(Stuff). Проблема в том, что вы можете создать экземпляр только с типом Stuff. Лучший подход — использовать нестатический метод, такой как @KayZ, опубликованный выше. - person Faris Nasution; 13.11.2013
comment
так что нет эквивалента «это» в «статическом»? - person H.R.; 13.11.2013
comment
Правильный. Даже если бы это было так, вы не смогли бы вызвать свою статическую функцию на Account, потому что она определена только на Stuff, а статические функции не наследуются. - person Dennis Kaselow; 14.11.2013