Есть метаклассы или ссылки на классы в D?
Есть ли какая-нибудь система ссылки на класс в D? Чтобы быть более точным, я ищу эквивалент Delphi
TMyClassRef = class of TMyClass;
Это будет использоваться для фабрики (так же, как в Object
но без использования имени класса):
// ideally
void AddNew(*TBaseClass APtr, /*?class_ref_type?*/ AClassType)
{
*APtr = new AClassType;
}
В настоящее время я делаю это:
void AddNew(*TBaseClass APtr)
{
*APtr = new typeof(*APtr);
}
Но проблема в том, что typeof()
всегда возвращается TBaseClass
и никогда не подкласс TBaseClass
(когда подкласс передается в качестве параметра). Это явно тот случай, когда ссылки на классы будут использоваться в Delphi, но язык D, похоже, не имеет такой системы.
2 ответа
Может быть, я полностью упускаю идею в Delphi, но, похоже, для этого нужны шаблоны:
import std.stdio;
class Parent {
string inherited() {
return "Hello from parent";
}
override string toString() {
return "Hello from parent";
}
}
class Child : Parent {
override string toString() {
return "Hello from child";
}
}
void add(C, P)(P* ptr) {
*ptr = new C;
}
void main() {
Parent t;
writeln(t); // prints null
add!Child(&t);
writeln(t); // prints Hello from child
writeln(t.inherited()); // prints Hello from parent
}
Таким образом, вы передаете тип, который вы хотите создать, вместо объекта этого типа. Это должно генерировать ошибки компиляции, если C не является потомком P в add().
Редактировать:
Если вы хотите быть более конкретным с add, вы можете сделать это:
void add(T : Parent)(Parent* ptr) {
*ptr = new T;
}
Чтобы сделать вещи лучше, используйте out
параметр, чтобы быть более идиоматическим:
void add(T : Parent)(out Parent ptr) {
ptr = new T;
}
void main() {
Parent p;
add!Child(p);
}
Насколько я понял концепцию Delphi, у D нет ссылок на классы в Delphi. Если вам нужно принять во время выполнения решение о строительстве объекта, object.TypeInfo
может помочь вам.
Вы можете получить TypeInfo
для переменной через typeid
построить:
import std.stdio;
class Base
{
void f()
{
writeln("Base");
}
}
class Descendant : Base
{
override void f()
{
writeln("Descendant");
}
}
Base makeNew(Base other)
{
// cast is needed because create() returns plain Object
// we can be sure it is Base at least, though, because it was crated from Base
return cast(Base)typeid(other).create();
}
void main()
{
Descendant source = new Descendant;
Base target = makeNew(source);
// prints "Descendant"
target.f();
}
Этот пример кода похож на то, что вы хотите?
D обычно имеет очень четкое различие между действиями во время выполнения и действиями во время компиляции. typeof
работает во время компиляции и поэтому не может запрашивать "реальный" тип класса в случае иерархий.