Как зайти в Даркнет?!
25th January, 01:11
8
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
899
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
952
0
Очень долго работает Update запрос Oracle
27th January, 09:58
916
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
907
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
942
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1727
0
период по дням
25th October, 10:44
3957
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3722
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4614
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4382
0
Помогите пожалуйста решить задачи
24th November, 23:53
6087
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4352
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4400
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Есть ли способ сделать конструктор видимым только для родительского класса в C#?
У меня есть коллекция классов, которые наследуются от абстрактного класса, который я создал. Я хотел бы использовать абстрактный класс в качестве фабрики для создания экземпляров конкретных реализаций моего абстрактного класса.
Есть ли способ скрыть конструктор от всего кода, кроме родительского класса.
Я хотел бы сделать это в основном
public abstract class AbstractClass
{
public static AbstractClass MakeAbstractClass(string args)
{
if (args == "a")
return new ConcreteClassA();
if (args == "b")
return new ConcreteClassB();
}
}
public class ConcreteClassA : AbstractClass
{
}
public class ConcreteClassB : AbstractClass
{
}
Но я хочу, чтобы никто не мог напрямую создавать экземпляры 2 конкретных классов. Я хочу убедиться, что только метод MakeAbstractClass() может создавать экземпляры базовых классов. Есть ли способ сделать это?
ОБНОВЛЕНИЕ
Мне не нужно обращаться к каким-либо конкретным методам ConcreteClassA или B из-за пределов абстрактного класса. Мне нужны только общедоступные методы, которые предоставляет мой абстрактный класс. Мне действительно не нужно предотвращать создание экземпляров конкретных классов, я просто пытаюсь избежать этого, поскольку они не предоставляют новых открытых интерфейсов, а просто разные реализации некоторых очень специфических вещей, внутренних для абстрактного класса.
Для меня самым простым решением является создание дочерних классов, как упоминал Сэмюэл. Я хотел бы избежать этого, однако, поскольку это сделало бы файл моего абстрактного класса намного больше, чем мне бы хотелось. Я бы предпочел, чтобы классы были разделены на несколько файлов для организации.
Я думаю, что нет простого решения для этого...
Для меня самое простое решение - это
сделайте дочерние классы как samjudson
упомянутый. Я бы хотел избежать этого
однако, поскольку это сделало бы мой
абстрактный класс ' файл намного больше, чем
Я бы хотел, чтобы так и было. Я бы предпочел сохранить
классы разделены на несколько файлов для
организация.
Для меня самое простое решение - это сделайте дочерние классы как samjudson упомянутый. Я бы хотел избежать этого однако, поскольку это сделало бы мой абстрактный класс ' файл намного больше, чем Я бы хотел, чтобы так и было. Я бы предпочел сохранить классы разделены на несколько файлов для организация.
Нет проблем, просто используйте частичное ключевое слово, и вы можете разделить свои внутренние классы на столько файлов, сколько захотите. Вы не должны хранить его в одном файле.
Предыдущий ответ:
Это возможно, но только с отражением
public abstract class AbstractClass
{
public static AbstractClass MakeAbstractClass(string args)
{
if (args == "a")
return (AbstractClass)Activator.CreateInstance(typeof(ConcreteClassA), true);
if (args == "b")
return (AbstractClass)Activator.CreateInstance(typeof(ConcreteClassB), true);
}
}
public class ConcreteClassA : AbstractClass
{
private ConcreteClassA()
{
}
}
public class ConcreteClassB : AbstractClass
{
private ConcreteClassB()
{
}
}
а вот еще один шаблон, без уродливых MakeAbstractClass (string args)
public abstract class AbstractClass<T> where T : AbstractClass<T>
{
public static T MakeAbstractClass()
{
T value = (T)Activator.CreateInstance(typeof(T), true);
// your processing logic
return value;
}
}
public class ConcreteClassA : AbstractClass<ConcreteClassA>
{
private ConcreteClassA()
{
}
}
public class ConcreteClassB : AbstractClass<ConcreteClassB>
{
private ConcreteClassB()
{
}
}
Вы можете сделать подклассы дочерними классами, что-то вроде этого:
public abstract class AbstractClass
{
public static AbstractClass MakeAbstractClass(string args)
{
if (args == "a")
return new ConcreteClassA();
if (args == "b")
return new ConcreteClassB();
}
private class ConcreteClassA : AbstractClass
{
}
private class ConcreteClassB : AbstractClass
{
}
}
@Vaibhav это действительно означает, что классы также скрыты. Но это, насколько мне известно, единственный способ полностью скрыть конструктор.
Edit: как уже упоминалось, то же самое можно сделать с помощью отражения, которое на самом деле может быть ближе к тому, что вы хотели бы иметь - например, приведенный выше метод отвечает на конкретные классы, находящиеся внутри того же файла, что и абстрактный класс, что, вероятно, не очень удобно. Сказав, что этот способ является хорошим 'Hack', и хорошо, если количество и сложность конкретных классов невелики.
Следуя принятому ответу, если у вас есть открытый интерфейс и частные классы реализуют интерфейс, вы можете затем вернуть указатель на интерфейс, и любой, кто находится за пределами вашего родительского абстрактного класса, может использовать их (все еще скрывая дочерние классы).
Если вы используете этот класс в отдельном сервисе assembly, вы можете использовать внутреннее ключевое слово.
public class AbstractClass
{
public AbstractClass ClassFactory(string args)
{
switch (args)
{
case "A":
return new ConcreteClassA();
case "B":
return new ConcreteClassB();
default:
return null;
}
}
}
public class ConcreteClassA : AbstractClass
{
internal ConcreteClassA(){ }
}
public class ConcreteClassB : AbstractClass
{
internal ConcreteClassB() {}
}
Вам действительно нужно это сделать? Если вы используете какой-то псевдо-заводской шаблон без истинной потребности в нем, вы только усложните свой код для понимания, поддержания и расширения.
Если вам не нужно этого делать, просто реализуйте истинный фабричный шаблон. Или, более ALTy, используйте структуру DI/IoC.
То, что вам нужно сделать, это предотвратить создание конструктора по умолчанию. Внутренний может быть изменен на public, если классы не находятся в том же assembly.
public abstract class AbstractClass{
public static AbstractClass MakeAbstractClass(string args)
{
if (args == "a")
return ConcreteClassA().GetConcreteClassA();
if (args == "b")
return ConcreteClassB().GetConcreteClassB();
}
}
public class ConcreteClassA : AbstractClass
{
private ConcreteClassA(){}
internal static ConcreteClassA GetConcreteClassA(){
return ConcreteClassA();
}
}
public class ConcreteClassB : AbstractClass
{
private ConcreteClassB(){}
internal static ConcreteClassB Get ConcreteClassB(){
return ConcreteClassB();
}
}