有没有办法让构造函数只对 C# 中的父类可见?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20185/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a way to make a constructor only visible to a parent class in C#?
提问by Dan Herbert
I have a collection of classes that inherit from an abstract class I created. I'd like to use the abstract class as a factory for creating instances of concrete implementations of my abstract class.
我有一组继承自我创建的抽象类的类。我想使用抽象类作为工厂来创建我的抽象类的具体实现的实例。
Is there any way to hide a constructor from all code except a parent class.
有没有办法从除父类之外的所有代码中隐藏构造函数。
I'd like to do this basically
我想基本上做到这一点
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
{
}
But I want to prevent anyone from directly instantiating the 2 concrete classes. I want to ensure that only the MakeAbstractClass() method can instantiate the base classes. Is there any way to do this?
但我想阻止任何人直接实例化 2 个具体类。我想确保只有 MakeAbstractClass() 方法可以实例化基类。有没有办法做到这一点?
UPDATE
I don't need to access any specific methods of ConcreteClassA or B from outside of the Abstract class. I only need the public methods my Abstract class provides. I don't really need to prevent the Concrete classes from being instantiated, I'm just trying to avoid it since they provide no new public interfaces, just different implementations of some very specific things internal to the abstract class.
更新
我不需要从抽象类外部访问 ConcreteClassA 或 B 的任何特定方法。我只需要我的抽象类提供的公共方法。我真的不需要阻止具体类被实例化,我只是想避免它,因为它们没有提供新的公共接口,只是抽象类内部一些非常具体的东西的不同实现。
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.
对我来说,最简单的解决方案是像 samjudson 提到的那样创建子类。但是,我想避免这种情况,因为它会使我的抽象类文件比我希望的要大得多。我宁愿将课程分成几个文件进行组织。
I guess there's no easy solution to this...
我想这没有简单的解决方案......
采纳答案by samjudson
You can make the sub classes child classes, something like this:
您可以将子类设为子类,如下所示:
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
{
}
}
@VaibhavThis does indeed mean that the classes are also hidden. But this is as far as I am aware the only way to completely hide the constructor.
@Vaibhav这确实意味着这些类也被隐藏了。但据我所知,这是完全隐藏构造函数的唯一方法。
Edit: As others have mentioned the same thing can be accomplished using Reflection, which might actually be closer to what you would like to be the case - for example the above method replies on the concrete classes being inside the same file as the Abstract class, which probably isn't very convenient. Having said that this way is a nice 'Hack', and good if the number and complexity of the concrete classes is low.
编辑:正如其他人提到的,使用反射可以完成同样的事情,这实际上可能更接近您想要的情况 - 例如,上述方法回复与抽象类位于同一文件中的具体类,这可能不是很方便。话虽如此,这种方式是一种不错的“技巧”,如果具体类的数量和复杂性较低,则很好。
回答by Vaibhav
No, I don't think we can do that.
不,我认为我们不能这样做。
回答by Rob Cooper
If the classes are in the same assembly, can you not make the constructors internal?
如果这些类在同一个程序集中,你不能让构造函数成为内部的吗?
回答by Rob Cooper
Do you actually needto do this? If you're using some kind of pseudo factory pattern without a true design need for it, you're only going to make your code harder to understand, maintain and extend.
你真的需要这样做吗?如果您使用某种伪工厂模式而没有真正的设计需求,那么您只会使您的代码更难理解、维护和扩展。
If you don't need to do this, just implement a true factory pattern. Or, more ALTy, use a DI/IoC framework.
如果您不需要这样做,只需实现一个真正的工厂模式。或者,更重要的是,使用 DI/IoC 框架。
回答by lubos hasko
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.
对我来说,最简单的解决方案是像 samjudson 提到的那样创建子类。但是,我想避免这种情况,因为它会使我的抽象类文件比我希望的要大得多。我宁愿将课程分成几个文件进行组织。
No problem, just use partialkeyword and you can split your inner classes into as many files as you wish. You don't have to keep it in the same file.
没问题,只需使用partial关键字,您就可以将内部类拆分为任意数量的文件。您不必将其保存在同一个文件中。
Previous answer:
上一个答案:
It's possible but only with reflection
这是可能的,但只能通过反射
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()
{
}
}
and here is another pattern, without ugly MakeAbstractClass(string args)
这是另一种模式,没有丑陋的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()
{
}
}
回答by Jedi Master Spooky
What you need to do is this to prevent the default constructor to be create. The internal can be change to public if the classes are not in the same 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();
}
}
回答by Peteter
Can't you use the keyword partial
for splitting the code for a class into many files?
不能使用关键字partial
将一个类的代码拆分成多个文件吗?
回答by FlySwat
If you are using this class in a seperate service assembly, you can use the internal keyword.
如果在单独的服务程序集中使用此类,则可以使用 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() {}
}
回答by Mark Ingram
Following on from the accepted answer, if you had a public interface and made the private classes implement the interface, you could then return a pointer to the interface and anyone outside of your parent abstract class could then use them (whilst still hiding the child classes).
继接受的答案之后,如果您有一个公共接口并使私有类实现该接口,则您可以返回一个指向该接口的指针,并且您的父抽象类之外的任何人都可以使用它们(同时仍然隐藏子类)。