Продвинутый полиморфизм
Короче, задача. Есть базовый класс. К примеру Connection. Его могут наследовать классы MSSQLConnection, OracleConnection и т.д. Количество класов-потомков мы в момент написания кода не знаем. В некотором класе-контейнере. Скажем VDataSource есть массив классов-родителей:
Connection [] ConnectionList= new Connection[MaxConnections];
Теперь - нужно написать код, который бы инициализировал каждый элемент массива, как класс, имя которого указывается в строке. То-есть при добавлении новых дочерних класов, про которые мы еще ничего не знаем, програмка бы могла с ними работать, без внедрения дополнительного кода.
То-есть что-б я мог инициализировать элемент каким-то таким кодом:
InitConnection(int NumberInArray, string ChildClassName);
P.S. Вообще-то пишу на С#, но такого раздела нет. Думаю здесь и место этой теме.
Вопрос к Green'у но если кто знает как сделать буду рад если подскажите.
Короче, задача. Есть базовый класс. К примеру Connection. Его могут наследовать классы MSSQLConnection, OracleConnection и т.д. Количество класов-потомков мы в момент написания кода не знаем. В некотором класе-контейнере. Скажем VDataSource есть массив классов-родителей:
Connection [] ConnectionList= new Connection[MaxConnections];
Теперь - нужно написать код, который бы инициализировал каждый элемент массива, как класс, имя которого указывается в строке. То-есть при добавлении новых дочерних класов, про которые мы еще ничего не знаем, програмка бы могла с ними работать, без внедрения дополнительного кода.
То-есть что-б я мог инициализировать элемент каким-то таким кодом:
InitConnection(int NumberInArray, string ChildClassName);
P.S. Вообще-то пишу на С#, но такого раздела нет. Думаю здесь и место этой теме.
Reflection не помогут?
using System.Reflection;
...
public static int Main(string[] args)
{
Assembly a=Assembly.Load("Connections");
Type t=a.GetType("Connections.MyNewConnection");
ConnectionList[num]=Activator.CreateInstance(t);
}
Connections - сборка, в которой хранятся различные потомки класса Connections. По идее должно работать.
Reflection не помогут?
using System.Reflection;
...
public static int Main(string[] args)
{
Assembly a=Assembly.Load("Connections");
Type t=a.GetType("Connections.MyNewConnection");
ConnectionList[num]=Activator.CreateInstance(t);
}
Connections - сборка, в которой хранятся различные потомки класса Connections. По идее должно работать.
Не знаю, первый раз слышу про такое. Буду смотреть.
Activator.CreateInstance че заменяет
new <название класса-потомка> ?
new <название класса-потомка> ?
Вроде да, только у Вас наверное в начале не надо ничего инициализировать, просто массив пустых ссылок, а CreateInstance вместо new. По крайней мере так в моей книге написано.
Вопрос к Green'у но если кто знает как сделать буду рад если подскажите.
Короче, задача. Есть базовый класс. К примеру Connection. Его могут наследовать классы MSSQLConnection, OracleConnection и т.д. Количество класов-потомков мы в момент написания кода не знаем. В некотором класе-контейнере. Скажем VDataSource есть массив классов-родителей:
Connection [] ConnectionList= new Connection[MaxConnections];
Теперь - нужно написать код, который бы инициализировал каждый элемент массива, как класс, имя которого указывается в строке. То-есть при добавлении новых дочерних класов, про которые мы еще ничего не знаем, програмка бы могла с ними работать, без внедрения дополнительного кода.
То-есть что-б я мог инициализировать элемент каким-то таким кодом:
InitConnection(int NumberInArray, string ChildClassName);
P.S. Вообще-то пишу на С#, но такого раздела нет. Думаю здесь и место этой теме.
К сожалению, я в C# не силен, поэтому могу сказать лишь обобщенно и как реализовать на С++.
Обобщенно.
Т.к. тебе заранее не известен тип объекта, тебе нужна фабрика, которая по названию будет возвращать объек соотв. типа с базовым интерфейсом.
Т.к. нужно чтоб введение нового дочернего класса не приводило к внедрению дополнительного кода в остальную часть программы, то нужно создать саморегистрацию классов в фабрике. IMHO это не очень хорошо, т.к. состав становится неявным.
В принципе, это похоже на то, что предложил neutrino4. CreateInstance - это и есть фабрика.
Если интересно, могу рассказать, как реализовать на С++.
К сожалению, я в C# не силен, поэтому могу сказать лишь обобщенно и как реализовать на С++.
Обобщенно.
Т.к. тебе заранее не известен тип объекта, тебе нужна фабрика, которая по названию будет возвращать объек соотв. типа с базовым интерфейсом.
Т.к. нужно чтоб введение нового дочернего класса не приводило к внедрению дополнительного кода в остальную часть программы, то нужно создать саморегистрацию классов в фабрике. IMHO это не очень хорошо, т.к. состав становится неявным.
В принципе, это похоже на то, что предложил neutrino4. CreateInstance - это и есть фабрика.
Если интересно, могу рассказать, как реализовать на С++.
В принципе я догадываюсь, но буду рад, обьяснению спеца на С++. Все таки интереснее чем книгу читать.
В принципе я догадываюсь, но буду рад, обьяснению спеца на С++. Все таки интереснее чем книгу читать.
Достаточно подробно это описано в книге А.Александреску "Современное проектирование на С++" (что-то сейчас никак не могу найти ссылку). Идея в том, что имеется некий объект-фабрика, содержащий в себе массив указателей на функции, создающие объекты, которые эта фабрика непосредственно и производит. При этом сам объект, желающий, чтобы его "типизированным" созданием занималась фабрика, эту функцию в ней и регистрирует. Для идентификации нужного вызова можно использовать ассоциативный массив. К примеру, как сказано в книге, ключами такого массива могут быть простые числа. Можно использовать также и typeinfo, хотя это не очень хорошее решение. В общем, как я помню, так. Green объяснит тебе лучше.
Достаточно подробно это описано в книге А.Александреску "Современное проектирование на С++" (что-то сейчас никак не могу найти ссылку). Идея в том, что имеется некий объект-фабрика, содержащий в себе массив указателей на функции, создающие объекты, которые эта фабрика непосредственно и производит. При этом сам объект, желающий, чтобы его "типизированным" созданием занималась фабрика, эту функцию в ней и регистрирует. Для идентификации нужного вызова можно использовать ассоциативный массив. К примеру, как сказано в книге, ключами такого массива могут быть простые числа. Можно использовать также и typeinfo, хотя это не очень хорошее решение. В общем, как я помню, так. Green объяснит тебе лучше.
Да, этому посвящена восьмая глава "Modern C++ design" А.Александреску.
Вот ссылка на эл.вариант:
http://anatolix.naumen.ru/Books/ModernCPPDesign?v=16g9
REmindER уже изложил идею, я повторяться не буду, посмотри у Александреску. Если что-то не понятно будет, помогу.
Да, этому посвящена восьмая глава "Modern C++ design" А.Александреску.
Вот ссылка на эл.вариант:
http://anatolix.naumen.ru/Books/ModernCPPDesign?v=16g9
REmindER уже изложил идею, я повторяться не буду, посмотри у Александреску. Если что-то не понятно будет, помогу.
Ты мне уже давал ссылку на Александреску. Я его скачал, и даже бумажный вариант купил. Просто еще пока ниасилил до 8 главы. Очень медленно заходит - не привык програмить обьектно-ориентировано. ;((
Хотя в целом идея понятна. Я думал, что скорее всего-придется вручную корректировать указатели на класс, предварительно поискав его в памяти. Сейчас вижу, что это довольно глупо. Идея с саморегистрацией класса в фабрике мне понравилась.