Ассоциативный массив, где класс TypeInfo является ключевым в D? - PullRequest
3 голосов
/ 02 июля 2010

Я хотел бы иметь возможность создать многомерный ассоциативный массив, в котором одно измерение является классом.Вот так:

class Node{
    Node[?classType?][string] inputs;
}

, чтобы я потом смог сделать

Node[] getInputsOfType(?? aClass){
   if(aClass in this.inputs)
      return this.inputs[aClass];
   else
      return null;
}

// meanwhile in another file...

Node[] effects = someAudioNode.getInputsOfType(AudioEffect);

Я просто потерян.Любые идеи?
Относительно последней части: Может ли класс использоваться как параметр сам по себе, как это?(AudioEffect в этом примере является классом.)

BR

[обновление / разрешение]

Спасибо за ответ (ы)!

Я думал, что было бы неплохо опубликовать результат.Хорошо, я посмотрел .classinfo в исходном коде и обнаружил, что он возвращает экземпляр TypeInfo_Class, и что есть .name -свойство, string.Вот что я придумал:

#!/usr/bin/env dmd -run
import  std.stdio;
class A{
    int id;
    static int newId;
    A[string][string] list;
    this(){ id = newId++; }
    void add(A a, string name){
        writefln("Adding: [%s][%s]", a.classinfo.name, name);
        list[a.classinfo.name][name] = a;
    }
    T[string] getAllOf(T)(){
        return cast(T[string]) list[T.classinfo.name];
    }
}
class B : A{ }
void main(){
    auto a = new A();
    a.add(new A(), "test");
    a.add(new B(), "bclass");
    a.add(new B(), "bclass2");

    auto myAList = a.getAllOf!(A);
    foreach(key, item; myAList)
        writefln("k: %s, i: %s id: %s",
                key, item.toString(), item.id);

    auto myBList = a.getAllOf!(B);
    foreach(key, item; myBList)
        writefln("k: %s, i: %s id: %s",
                key, item.toString(), item.id);
}

Вывод:

Adding: [classtype.A][test]
Adding: [classtype.B][bclass]
Adding: [classtype.B][bclass2]
Trying to get [classtype.A]
k: test, i: classtype.A id: 1
Trying to get [classtype.B]
k: bclass2, i: classtype.B id: 3
k: bclass, i: classtype.B id: 2

Так что да, я полагаю, это работает.Yey!У кого-нибудь есть идеи по улучшению?

Есть ли здесь какие-нибудь подводные камни?

  • Может ли classinfo.name внезапно вести себя непредсказуемо?
  • Есть ли "правильный" способ получения имени класса?

Кроме того, этосамый быстрый способ сделать это?Я имею в виду, что имена всех классов начинаются с classtype..Ну да ладно, это, пожалуй, еще один SO-поток.Еще раз спасибо!

BR

1 Ответ

3 голосов
/ 02 июля 2010

Вы можете использовать класс ClassInfo (доступный через свойство .classinfo) для ссылки на типы классов во время выполнения. Однако класс ClassInfo не реализует необходимые методы, которые должны использоваться в ассоциативном массиве (см. Справочную страницу D на AAs относительно использования классов / структур в AA). Я полагаю, это возможно, если вы реализуете свою собственную обертку для ClassInfo, которую можно использовать в качестве ключа AA. Это должно быть довольно просто, поскольку вы можете ожидать, что тип класса будет иметь только один экземпляр ClassInfo, поэтому вы можете просто использовать адрес ClassInfo в качестве уникального хэша.


Кстати, более простой и быстрый способ написать

if (key in aa)
    return aa[key];
else
    return null;

есть

auto pvalue = key in aa;
return pvalue ? *pvalue : null;
...