How to force overriding a method in a descendant, without having an abstract base class?

前端 未结 14 903
孤城傲影
孤城傲影 2020-12-09 07:24

Question Heading seems to be little confusing, But I will Try to clear my question here.

using System;
using System.Collections.Generic;
usi         


        
相关标签:
14条回答
  • 2020-12-09 07:58

    I feel like this indicates that your implementation really has two parts: a partial implementation that goes in the base class, and a missing completion to that implementation that you want in the sub class. Ex:

    public abstract class Base
    {
       public virtual void PartialImplementation()
       {
          // partial implementation
       }
    }
    
    public sealed class Sub : Base
    {
       public override void PartialImplementation()
       {
          base.PartialImplementation();
          // rest of implementation
       }
    }
    

    You want to force the override, since the initial implementation is incomplete. What you can do is split your implementation into two parts: the implemented partial part, and the awaiting-implementation missing part. Ex:

    public abstract class Base
    {
       public void PartialImplementation()
       {
          // partial implementation
    
          RestOfImplementation();
       }
    
       // protected, since it probably wouldn't make sense to call by itself
       protected abstract void RestOfImplementation();      
    }
    
    public sealed class Sub : Base
    {
       protected override void RestOfImplementation()
       {
          // rest of implementation
       }
    }
    
    0 讨论(0)
  • 2020-12-09 07:59

    You can not, unless you make SalesPerson abstract or change the hierarchy.

    How about:

                           Employee*
                               ^
                               |
                           SalesPersonBase* (have all the code except GiveBonus)
                            ^           ^
                            |           |
                     SalesPerson      PTSalesPerson
    

    Both Employee and SalesPersonBase are now marked as abstract.

    However, if you require a PTSalesPerson to not only inherit behavior, but also inherit the is-a relationship (a PTSalesPerson is also a SalesPerson), then you have no way of forcing this.

    Note, the above text is only valid if you only consider compile-time checks. In other words, if you want the compiler to complain if you haven't added an override to the PTSalesPerson class, you cannot do that, unless you do what I outlined above.

    However, there's nothing stopping you from using reflection to examine the methods at runtime, and throw an exception if the method in PTSalesPerson is not explicitly overridden there, however I would consider that a hack.

    0 讨论(0)
  • 2020-12-09 08:01

    Use dependency injection. Create a BonusCalculator class:

    public abstract class BonusCalculator
    {
       public abstract decimal CalculateBonus(Employee e)
    }
    

    In your base class:

    private BonusCalculator Calculator { get; set; }
    
    public void GiveBonus()
    {
       Bonus = Calculator.CalculateBonus(this)
    }
    

    In your implementation's constructor:

    public SomeKindOfEmployee()
    {
        Calculator = new SomeKindOfEmployeeBonusCalculator();
    }
    

    Someone implementing a Person subclass now has to explicitly provide it with an instance of a BonusCalculator (or get a NullReferenceException in the GiveBonus method).

    As an added, er, bonus, this approach allows different subclasses of Person to share a bonus-calculation method if that's appropriate.

    Edit

    Of course, if PTSalesPerson derives from SalesPerson and its constructor calls the base constructor, this won't work either.

    0 讨论(0)
  • 2020-12-09 08:02

    You could always make SalesPerson's implementation throw a NotImplementedException. :V But contractually, no, you can't do that.

    0 讨论(0)
  • 2020-12-09 08:05

    This is a very old thread but the answer given on this question can be usefull. You can force a derived class to have its own implementation of a virtual method/property.

    public class D
    {
        public virtual void DoWork(int i)
        {
            // Original implementation.
        }
    }
    
    public abstract class E : D
    {
        public abstract override void DoWork(int i);
    }
    
    public class F : E
    {
        public override void DoWork(int i)
        {
            // New implementation.
        }
    }
    

    If a virtual method is declared abstract, it is still virtual to any class inheriting from the abstract class. A class inheriting an abstract method cannot access the original implementation of the method—in the previous example, DoWork on class F cannot call DoWork on class D. In this way, an abstract class can force derived classes to provide new method implementations for virtual methods.

    0 讨论(0)
  • 2020-12-09 08:05

    The only way i can see of making this work, if you can not make SalesPerson Abstract, is this:

    1) in SalesPerson.GiveBonus(...) use reflection to determine if 'this' is a SalesPerson, or a derived class a) if not a derived class, do current code in SalesPerson.GiveBonus b) otherwise call GiveBonusDerived. (declare this as virtual, and make the implmentation in SalesPerson throw an exception.)

    The draw backs here are, Reflection is slow. No compile time error if GiveBonusDerived isn't declared, etc.

    0 讨论(0)
提交回复
热议问题