有没有办法使构造函数仅对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 { }
但是我想防止任何人直接实例化这两个具体的类。我想确保只有MakeAbstractClass()方法可以实例化基类。有什么办法吗?
更新
我不需要从Abstract类的外部访问ConcreteClassA或者B的任何特定方法。我只需要Abstract类提供的公共方法。我并不需要阻止实例化具体类,我只是想避免这样做,因为它们没有提供新的公共接口,只是抽象类内部某些非常特定的东西的不同实现。
对我来说,最简单的解决方案是像samjudson所提到的那样创建子类。但是,我想避免这种情况,因为它会使我的抽象类文件变得比我想要的要大得多。我宁愿将类分成几个文件进行组织。
我想对此没有简单的解决方案...
解决方案
回答
不,我认为我们无法做到这一点。
回答
我们可以使子类成为子类,如下所示:
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这确实意味着这些类也被隐藏了。但是据我所知,这是完全隐藏构造函数的唯一方法。
编辑:正如其他人所提到的,使用Reflection可以完成相同的事情,这实际上可能更接近于我们想要的情况,例如,上述方法将具体类答复为与Abstract类在同一文件内,可能不是很方便。话虽这么说,这是一个很好的" Hack",如果具体类的数量和复杂性很低,则很好。
回答
如果这些类在同一程序集中,则不能使构造函数成为内部的吗?
回答
我们实际上需要这样做吗?如果我们使用某种伪工厂模式而不需要真正的设计,那么只会使代码更难于理解,维护和扩展。
如果我们不需要这样做,只需实现一个真正的工厂模式即可。或者,更高级,使用DI / IoC框架。
回答
To me, the simplest solution is to make child classes as samjudson mentioned. I'd like to avoid this however since it would make my abstract class' file a lot bigger than I'd like it to be. I'd rather keep classes split out over a few files for organization.
没问题,只需使用partial关键字,我们就可以将内部类拆分为任意数量的文件。我们不必将其保存在同一文件中。
先前的答案:
有可能,但只有反思
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。
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(); } }
回答
我们不能使用关键字" partial"将一个类的代码拆分为多个文件吗?
回答
如果要在单独的服务程序集中使用此类,则可以使用internal关键字。
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() {} }
回答
从接受的答案开始,如果我们有一个公共接口并让私有类实现该接口,则可以返回一个指向该接口的指针,然后父抽象类之外的任何人都可以使用它们(尽管仍然隐藏子类)。