Наследование Delphi-интерфейса с дженериками
в настоящее время я застрял с ошибкой компиляции, никто в нашей компании не может помочь, и я, к сожалению, не нахожу правильные шаблоны поиска для SO или google.
в качестве кода я использую 2 интерфейса, унаследованные и 2 класса, унаследованные. Следующий код воспроизводит ошибку:
program Project22;
{$APPTYPE CONSOLE}
type
IStorageObject = interface(IInterface)
end;
TObjectStorage<T: IStorageObject> = class(TObject)
end;
IKeyStorageObject<TKey> = interface(IStorageObject)
end;
TKeyObjectStorage<TKey, T: IKeyStorageObject<TKey>> = class(TObjectStorage<T>)
end;
TImplementingClass<TKey> = class(TInterfacedObject, IKeyStorageObject<TKey>)
end;
begin
TKeyObjectStorage<Integer, TImplementingClass<Integer>>.Create;
end.
ошибка компилятора для "TKeyObjectStorage":
[ошибка DCC] Project22.dpr (11): e2514 тип параметр ' T ' должен поддерживать интерфейс 'IStorageObject'
Я думаю, что компилятор не распознает этот параметр t класса 'TKeyObjectStorage' правильно. Это должно быть правильно, так как разыскиваемый тип "IKeyStorageObject" имеет родительский тип IStorageObject.
почему это не работает? Что я делаю не так? Разве это невозможно в Дельфах?
1 ответов
обновление
в исходном вопросе была проблема, которую я определил (см. ниже). Однако я описываю есть штраф за XE3 и позже, но программа не компилируется в XE2 в. Таким образом, я заключаю, что это ошибка компилятора XE2 generics.
в любом случае, вот решение для Делфи XE2 в:
{$APPTYPE CONSOLE}
type
IStorageObject = interface(IInterface)
end;
TObjectStorage<T: IStorageObject> = class(TObject)
end;
IKeyStorageObject<TKey> = interface(IStorageObject)
end;
TKeyObjectStorage<TKey; T: IKeyStorageObject<TKey>, IStorageObject> = class(TObjectStorage<T>)
end;
TImplementingClass<TKey> = class(TInterfacedObject, IStorageObject, IKeyStorageObject<TKey>)
end;
begin
TKeyObjectStorage<Integer, TImplementingClass<Integer>>.Create;
end.
оригинальный ответ
было бы лучше, если вы предоставил полную программу, которая показала ошибку компилятора. Вам нужно попытаться создать экземпляр объекта, чтобы увидеть эту ошибку.
но, думаю, я воспроизвел вашу проблему. Поэтому я считаю, что проблема в том, что этот код:
TKeyObjectStorage<TKey, T: IKeyStorageObject<TKey>> = ...
применяет общее ограничение к обоим TKey
и T
. Теперь ясно, что вы хотите, чтобы ограничение применялось только к T
поэтому вам нужно написать:
TKeyObjectStorage<TKey; T: IKeyStorageObject<TKey>> = ...
вот короткая программа, которая компилирует следующий изменение в Делфи XE3 установлены:
{$APPTYPE CONSOLE}
type
IStorageObject = interface(IInterface)
end;
TObjectStorage<T: IStorageObject> = class(TObject)
end;
IKeyStorageObject<TKey> = interface(IStorageObject)
end;
TKeyObjectStorage<TKey; T: IKeyStorageObject<TKey>> = class(TObjectStorage<T>)
end;
TImplementingClass<TKey> = class(TInterfacedObject, IKeyStorageObject<TKey>)
end;
begin
TKeyObjectStorage<Integer, TImplementingClass<Integer>>.Create;
end.
это довольно нюанс, изменение запятой на точку с запятой. Программирование значительными пунктуациями никогда не доставляет удовольствия. Тем не менее, вы знакомы с разницей между запятыми и полуколонами в формальных списках параметров, и поэтому не должно быть слишком большим сюрпризом увидеть то же самое различие, проведенное здесь.
на документация прикрывает это внимание:
Несколько Параметров Типа
когда вы указываете ограничения, вы отделяете несколько параметров типа по точки с запятой, как и при объявлении списка параметров:
type TFoo<T: ISerializable; V: IComparable>
как объявления параметров, несколько параметров типа могут быть сгруппированы вместе в списке запятых для привязки к тем же ограничениям:
type TFoo<S, U: ISerializable> ...
в приведенном выше примере,
S
иU
оба связаны сISerializable
ограничение.