【问题标题】:Optional Parameters in Abstract method? Is it possible?抽象方法中的可选参数?可能吗?
【发布时间】:2013-11-17 00:22:13
【问题描述】:

我有一个抽象基类。

我有 2 个从这个基类派生的类。

无论如何我的一个类可以忽略抽象覆盖用法中的字符串参数吗? 还是我只需要发送一个空白的并忽略它? (使可读性略有下降)

我能否拥有一个具有某种可选参数的函数,以便以下两个派生类都可以编译?

PS - 以下代码充斥着无法编译的代码,作为我想做的示例

PS PS - 是的,我已经编译了以下代码 - 请参阅上面的评论以了解结果

public abstract class MyBaseClass
{                                            //optional string?
    public abstract void FunctionCall(int i, string s = "");
}

public class MyDerivedClass : MyBaseClass
{
    public override void FunctionCall(int i)
    {
        MessageBox.Show(i.ToString());
    }
}

public class YourDerivedClass : MyBaseClass
{
    public override void FunctionCall(int i, string s)
    {
        MessageBox.Show(s + " " + i.ToString());
    }
}

【问题讨论】:

    标签: c# class abstract optional-parameters derived-class


    【解决方案1】:

    如果你不是绝对需要 FunctionCall 是抽象的,你可以声明它的两个版本:

    public abstract class MyBaseClass
    {
        public virtual void FunctionCall(int i)
        {
            this.FunctionCall(i, "");
        }
        public virtual void FunctionCall(int i, string s)
        {
    
        }
    }
    
    public class MyDerivedClass : MyBaseClass
    {
        public override void FunctionCall(int i)
        {
            MessageBox.Show(i.ToString());
        }
    }
    
    public class YourDerivedClass : MyBaseClass
    {
        public override void FunctionCall(int i, string s)
        {
            MessageBox.Show(s + " " + i.ToString());
        }
    }
    

    否则,如果它必须是抽象的以确保它被实现,你仍然可以添加两个版本,它只是让继承者更加冗长:

    public abstract class MyBaseClass
    {
        public abstract void FunctionCall(int i);
        public abstract void FunctionCall(int i, string s);
    }
    
    public class MyDerivedClass : MyBaseClass
    {
        public override void FunctionCall(int i, string s)
        {
            throw new NotImplementedException();
        }
        public override void FunctionCall(int i)
        {
            MessageBox.Show(i.ToString());
        }
    }
    
    public class YourDerivedClass : MyBaseClass
    {
        public override void FunctionCall(int i)
        {
            throw new NotImplementedException();
        }
        public override void FunctionCall(int i, string s)
        {
            MessageBox.Show(s + " " + i.ToString());
        }
    }
    

    【讨论】:

    • 使它们与抽象相对的虚拟有什么缺点?
    • 不客气。使它们成为虚拟的主要缺点是它们不再需要由继承者实现。这对您的应用程序的影响完全取决于这些方法的功能以及该类是否会被外部调用者使用。仅仅因为冗长,我的首选方法是将它们实现为虚拟并在基类中抛出未实现的异常。通过适当的单元测试,这与将它们声明为抽象具有相同的效果。
    【解决方案2】:

    会抛出编译错误:“Abstract Inherited member 'MyBaseClass.FunctionCall(int, string)' is not implemented”。

    所以不,简短的回答是你不能这样做。

    相反,您必须进行方法重载并实现两个抽象方法。

    public abstract class MyBaseClass
    {    
        public abstract void FunctionCall(int i);                                        
        public abstract void FunctionCall(int i, string s = "");
    }
    
    public class MyDerivedClass : MyBaseClass
    {
        public override void FunctionCall(int i, string s = "") { }
    
        public override void FunctionCall(int i)
        {
            MessageBox.Show(i.ToString());
        }
    }
    
    public class YourDerivedClass : MyBaseClass
    {
        public override void FunctionCall(int i, string s)
        {
            MessageBox.Show(s + " " + i.ToString());
        }
    
        public override void FunctionCall(int i) {}
    }
    

    但是,这似乎很混乱。也许最好的选择是始终使用可选参数,如果不需要,就不要传入一个值,或者像你已经在做的那样处理它。

    public class MyDerivedClass : MyBaseClass
    {
        public override void FunctionCall(int i, string s = "") 
        {
            if (!string.IsNullOrEmpty(s))
                MessageBox.Show(i.ToString());
            else
               // handle other path here
        }
    }
    

    【讨论】:

      【解决方案3】:

      一种可能的方法是使用扩展方法来添加缺失的覆盖(这也适用于接口)

      static class MyBaseClassExtensions
      {
             public void FunctionCall(MyBaseClass this item, int i)
             {
                  item.FunctionCall(i, null);
             }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-17
        • 1970-01-01
        • 2015-01-19
        • 2011-05-04
        • 1970-01-01
        • 1970-01-01
        • 2021-10-16
        • 2011-11-16
        相关资源
        最近更新 更多