【问题标题】:Is there a way to make a constructor only visible to a parent class in C#?有没有办法让构造函数只对 C# 中的父类可见?
【发布时间】:2010-09-06 10:02:31
【问题描述】:

我有一组继承自我创建的抽象类的类。我想将抽象类用作创建抽象类的具体实现实例的工厂。

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

基本上我也想做这个

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() 方法可以实例化基类。有没有办法做到这一点?

更新
我不需要从 Abstract 类外部访问 ConcreteClassA 或 B 的任何特定方法。我只需要我的 Abstract 类提供的公共方法。我真的不需要阻止具体类被实例化,我只是想避免它,因为它们没有提供新的公共接口,只是抽象类内部一些非常具体的东西的不同实现。

对我来说,最简单的解决方案是make child classes as samjudson mentioned。但是我想避免这种情况,因为它会使我的抽象类的文件比我希望的要大得多。我宁愿将课程分成几个文件进行组织。

我想这个问题没有简单的解决方案......

【问题讨论】:

    标签: c# inheritance oop


    【解决方案1】:

    对我来说,最简单的解决方案是 将子课程设为 samjudson 提及。我想避免这种情况 然而,因为它会让我 抽象类的文件比 我希望它是。我宁愿保留 类拆分为几个文件 组织。

    没问题,只需使用 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()
        {
        }
    }
    

    【讨论】:

      【解决方案2】:

      如果类在同一个程序集中,可以不将构造函数设为内部吗?

      【讨论】:

        【解决方案3】:

        您可以将子类设为子类,如下所示:

        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 这确实意味着这些类也被隐藏了。但据我所知,这是完全隐藏构造函数的唯一方法。

        编辑:正如其他人提到的,同样的事情可以使用反射来完成,这实际上可能更接近您想要的情况 - 例如,上述方法回复与位于同一文件中的具体类抽象类,这可能不是很方便。话虽如此,这种方式是一种很好的“Hack”,如果具体类的数量和复杂性较低,则很好。

        【讨论】:

        • 很好的例子,但是为了编码标准,让命名更 .NETy 并称之为“CreateAbstractClass(string args)”:)
        【解决方案4】:

        不,我认为我们做不到。

        【讨论】:

          【解决方案5】:

          accepted answer 开始,如果您有一个公共接口并让私有类实现该接口,那么您可以返回一个指向该接口的指针,然后您的父抽象类之外的任何人都可以使用它们(虽然仍然隐藏子类)。

          【讨论】:

            【解决方案6】:

            您真的需要这样做吗?如果您使用某种伪工厂模式而没有真正的设计需求,您只会让您的代码更难理解、维护和扩展。

            如果您不需要这样做,只需实现真正的工厂模式即可。或者,更多的 ALTy,使用 DI/IoC 框架。

            【讨论】:

              【解决方案7】:

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

              【讨论】:

                【解决方案8】:

                如果您在单独的服务程序集中使用此类,则可以使用 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() {}
                }
                

                【讨论】:

                  【解决方案9】:

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

                  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();
                    }
                  
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2019-06-06
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2020-12-26
                    • 1970-01-01
                    • 2014-02-14
                    • 2015-10-11
                    相关资源
                    最近更新 更多