关于继承:有没有办法使构造函数仅对C#中的父类可见?

关于继承:有没有办法使构造函数仅对C#中的父类可见?

Is there a way to make a constructor only visible to a parent class in C#?

我有一个从我创建的抽象类继承的类的集合。我想将抽象类用作创建我的抽象类的具体实现实例的工厂。

有什么方法可以从父类以外的所有代码中隐藏构造函数。

我想基本上做到这一点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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所提到的那样创建子类。但我想避免这种情况,因为它会使我的抽象类文件变得比我想要的要大得多。我宁愿将类分成几个文件进行组织。

我想没有简单的解决方案...


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关键字,您就可以将内部类拆分为任意数量的文件。您不必将其保存在同一文件中。

先前的答案:

有可能,但只有反思

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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(s??tring args)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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()
    {
    }
}

如果这些类在同一程序集中,则不能使构造函数成为内部的吗?


您可以使子类成为子类,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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",如果具体类的数量和复杂性较低,则很好。


从接受的答案开始,如果您有一个公共接口并让私有类实现该接口,则可以返回一个指向该接口的指针,然后您的父抽象类之外的任何人都可以使用它们(尽管仍然隐藏了子类) )。


不,我认为我们无法做到这一点。


如果要在单独的服务程序集中使用此类,则可以使用internal关键字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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() {}
}

您不能使用关键字partial将一个类的代码拆分为多个文件吗?


您实际上需要这样做吗?如果您使用某种伪工厂模式而不需要真正的设计,那么只会使您的代码难以理解,维护和扩展。

如果您不需要这样做,只需实现一个真正的工厂模式。或者,更高级,使用DI / IoC框架。


您需要做的是防止创建默认构造函数。如果这些类不在同一程序集中,则内部可以更改为public。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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();
  }

}

推荐阅读