【问题标题】:Abstract method vs static method in Program classProgram 类中的抽象方法与静态方法
【发布时间】:2013-06-25 16:16:04
【问题描述】:

假设我有一个简单的继承链,其中Employee 是抽象基类,CheckoutManager 在这个纯粹说明性的控制台应用程序中继承自它。现在我想要一个方法,它可以接收ManagerCheckout 类型的对象,并根据员工在公司的职位返回整数数量的奖金。我对此有一些初步的想法,并且想知道如果这个控制台应用程序有朝一日成长为数据驱动的 Web 应用程序,每种方法的潜在长期缺陷或收益。

  1. 使用继承类通用的接口。 我的基类看起来像

    abstract class Employee
        {
            public int EmployeeId { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
    
    
        }
    

    我的派生类实现了一个接口,旨在将员工信息打印到名为IPrintable 的控制台,并且只有一种方法可以这样做。虽然这个界面与奖励无关,但我在课堂上用我的Main 方法模拟了以下内容,并且程序运行良好。

    static int GiveBonusesViaInterface(IPrintable i)
            {
                if (i is Checkout)
                    return 1000;
                else 
                    return 2000;
    
    
            }
    

    在我看来,如果我想为此使用一个界面,我可能应该再制作一个专门用于加薪的界面,而不是在已经实现的界面上束手无策(但这是另一天的另一个问题)。

  2. 在基类中使用静态方法

    public static int GiveBonus(Employee e)
            {
                if (e is Manager)
                    return 2000;
                else
                    return 1000;
            }
    
  3. 在抽象基类中创建一个抽象方法,并按照他们认为合适的方式实现派生类

    abstract class Employee
    //fields and constructors
    {
    public abstract int GiveBonusesViaAbstractMethod(Employee e); 
    }
    

这对我来说似乎是最糟糕的想法,因为在每个派生类中都必须有一个方法,该方法接受 IPrintableEmployee 类型的参数,并且在 Manager 类中我们必须测试是否员工is-a经理。

对于长期 Web 应用程序,1-2 是否同样具有可扩展性和可管理性?选项 3 真的像我说的那么糟糕吗?

【问题讨论】:

  • 我认为exist方法(使用接口)比其他方法更好
  • 哦,不,这越来越糟了。不要把你的逻辑散布出去,绝对不要用Main把它放在你的静态类中。写一个静态方法很好,但是把它放在抽象的Employee 类中——如果你必须有一个方法的话。

标签: c# visual-studio-2010


【解决方案1】:

您错过了执行此操作的传统 OO 方式:

abstract class Employee {
    public int EmployeeId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public abstract int GetBonusAmount();
}

class Manager : Employee {
    public override int GetBonusAmount() { return 2000; } 
}

class Checkout : Employee {
    public override int GetBonusAmount() { return 1000; } 
}

Console.WriteLine(someEmployee.GetBonusAmount());

【讨论】:

  • public override int BonusAmount{get{return 1000;}}
  • @SamIam 是的,抽象属性在这里也同样适用。这完全取决于实现 - 如果它是动态或计算值,我可能会使用一种方法。这并不重要,因为无论如何它都是相同的代码,只是一种风格。
【解决方案2】:

我认为您确实已经回答了自己的问题。

我的派生类实现了一个接口,旨在将员工信息打印到名为IPrintable 的控制台,并且只有一种方法可以这样做。虽然这个界面与发放奖金无关

[强调我的]

您已经有一个用于此的接口。它被称为Employee。这样做的惯用方法是在您的抽象类上实现一个虚拟方法,并在必要时覆盖。更惯用的 C# 方法是编写一个属性并覆盖它。像这样:

abstract class Employee {
  public virtual int GetBonus()
  {
    return this.Bonus;
  }

  public virtual int Bonus { get; set; }
}

class Manager : Employee {
  public override int Bonus 
  { 
    get { return 2000; }
  }
}

class Checkout : Employee {
  public override int Bonus
  {
    get { return 1000; }
  }
}

【讨论】:

  • 这是不是比在 Employee 基类中创建静态方法更面向对象的方法?
  • 我不知道我一定会称它为“更多 OO”。静态方法也可以很容易地使用。你只需要传递一个Employee 参数并使用它而不是this
  • 我最初将方法设为静态的原因是,我只需要在一个地方更改返回值(例如,如果逻辑变得更复杂)。这是一个合理的担忧,还是有些愚蠢的担忧?
  • 该方法是否是静态的并不影响您必须编辑多少地方才能进行更改。您根本不需要重写该方法。真的,你不需要一种方法——除非你正在做一些非常复杂的事情来计算奖金数额。最好只拥有属性。
【解决方案3】:

在两个子类中实现 GetBonus() 方法。您应该完全避免执行“is instance of”检查。

【讨论】:

  • @wootscootinboogie 你不需要知道。利用类型系统。这就是继承和多态性的全部意义所在。
【解决方案4】:

我认为抽象效果很好:

abstract class Employee
{
    public int EmployeeId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public abstract int GetVariableBonus();
}

class Manager {
    public int GetVariableBonus(){
         return 2000;
    }
}

class Employee{
    public int GetVariableBonus(){
         return 1000;
    }
}

这是你需要的吗?

【讨论】:

  • 这基本上是一样的,但我选择将抽象方法设为静态,因为我只需要潜在地更改一个类(基类)与所有继承的类中的返回值。
  • @woots 这违反了开放封闭原则。类应该对扩展开放,对修改关闭。
猜你喜欢
  • 2012-12-03
  • 2011-09-26
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
  • 1970-01-01
  • 1970-01-01
  • 2014-03-19
  • 1970-01-01
相关资源
最近更新 更多