73

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    public abstract class Employee
    {
        private string name;
        private int empid;
        BenefitPackage _BenefitPackage = new BenefitPackage();
        public string Name
         {
             get { return this.name; }
             set { this.name = value; }
            }
        public int EmpId
        {
            get { return this.empid; }
            set
            {
                if (value == 1)
                    return;
                this.empid = value; }
        }
        public Employee(string Name, int EmpId)
        {
            this.Name = Name;
            this.EmpId = EmpId;
        }
        public Employee()
        { }

        public abstract void GiveBonus();

    }

    public class Manager : Employee
    {
        private int noofstockoptions;
        public override void GiveBonus()
        {
            Console.WriteLine("Manger GiveBonus Override");
        }
        public int NoOfStockOptions
        {
            get { return this.noofstockoptions; }
            set { this.noofstockoptions = value; }
        }

        public Manager(string Name,int EmpId, int NoOfStockOptions):base(Name,EmpId)
        {
            this.NoOfStockOptions=NoOfStockOptions;
        }

    }
    public class SalesPerson:Employee
    {
        private int noofsales;
        public int NoOfSales
        {
            get { return this.noofsales; }
            set { this.noofsales = value; }
        }

        public SalesPerson(string Name, int EmpId, int NoOfSales):base(Name,EmpId)
        {
            this.NoOfSales = NoOfSales;
        }
        public override void GiveBonus()
        {
            Console.WriteLine("Hi from salesperson");
        }
    }
    public sealed class PTSalesPerson : SalesPerson
    {
        private int noofhrworked;
        public int NoOfHrWorked
        {
            get { return this.noofhrworked; }
            set { this.noofhrworked = value; }

        }
        public PTSalesPerson(string Name, int EmpId, int NoOfSales,int NoOfHrWorked):base(Name,EmpId,NoOfSales)
        {
            this.NoOfHrWorked = NoOfHrWorked;

        }
        //public new void GiveBonus()
        //{
        //    Console.WriteLine("hi from ptsalesperson");
        //} 
    }

    class BenefitPackage
    {
        public int Bonus;
        public int GiveBonus()
        {
            int i = 200;
            return i;
        }

        private class innerPublic
        {
            public int innerBonus;

        }


    }

    class MainClass
    {
        public static void Main()
        { 
        Manager _Manager=new Manager("Vaibhav",1,50);
        PTSalesPerson _PTSalesPerson = new PTSalesPerson("Shantanu", 1, 4, 6);
        _Manager.GiveBonus();

        Employee _emp;
        //_emp = new Employee("new emp",4);
        //_emp.GiveBonus();
        _PTSalesPerson.GiveBonus();
        ((SalesPerson)_PTSalesPerson).GiveBonus();
        Console.ReadLine();    
        }

    }
}

Please do not try to understand the whole code. I am summarising it.

  1. Employee is a Abstract class, which have an abstract method GiveBonus
  2. SalesPerson is a deriving from Employee. SalesPerson has to give definition to abstract Method GiveBonus.(SalesPerson can not be Abstract)
  3. PTSalesPerson is deriving from SalesPerson.

Now my question is, How can I force PTSalesPerson to have its own implementation of GiveBonus.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
Vaibhav Jain
  • 33,887
  • 46
  • 110
  • 163
  • Is this a duplicate of http://stackoverflow.com/questions/239408? – Simon Jan 22 '10 at 15:10
  • 2
    I would use an Interface. Have a base emloyee interface and a sales person interface. The sales person then implements both sales person interface and employee interface. This way you can force the implementation of specific methods. – nivs1978 Jun 01 '21 at 06:30
  • 1
    @nivs1978 - that won't accomplish the goal (by itself). The situation is that class SalesPerson already implements the required sales method. Thereby satisfying the sales interface. The requirement is that any subclass MUST override that existing method. Yet it cannot be made abstract in SalesPerson. – ToolmakerSteve Oct 16 '21 at 04:29
  • Most of these answers either fail to accomplish the goal, or are unnecessarily complicated. Change the implementation heirarchy: Use [Karlsen's](https://stackoverflow.com/a/2118116/199364). Create an abstract base class shared by both SalesPerson and PTSalesPerson, call it SalesPersonBase. Put all of SalesPerson's methods in there, except the one that subclasses must override (GiveBonus). Then declare SalesPersonBase's GiveBonus abstract. Note that this means `SalesPersonBase` is the class you test for, if you need to refer to all SalesPerson's. – ToolmakerSteve Oct 16 '21 at 04:36
  • Or equivalently: Make `SalesPerson` an abstract class. Create a subclass `DefaultSalesPerson` (or whatever name conveys to you that this is the "go-to" if there are no special conditions). Make SalesPerson's GiveBonus abstract. Move its implementation into `DefaultSalesPerson`. This keeps a simple name for the common base class. Create new instances using a static "factory" method in `SalesPerson`, to which you give parameters indicating special requirements. If no special requirements, it returns a `new DefaultSalesPerson`. All variables elsewhere can now simply refer to `SalesPerson`. – ToolmakerSteve Oct 16 '21 at 04:45

14 Answers14

113

I think you're thinking about this the wrong way. The language designers did not say to themselves "what we really need is a way to mark a method as must be overridden, let's invent this thing called abstract". They said "A virtual method lets us represent the idea that every derived type of this base type should be able to do this method. But what if there is no sensible code that can possibly go in the base class version of the method? I know, let's invent this thing called an abstract method for that circumstance."

That's the problem that abstract methods were intended to solve: you have a method common to all derived classes but no sensible base class implementation, NOT "I need a way to force my derived types to provide an implementation". That derived types are forced to provide an implementation is a consequence of the solution, but not the problem intended to be solved in the first place.

The C# language does not have a mechanism for the problem "I must force my subtype to provide their own implementation of this method" because that's not a problem that the language designers, to my knowledge, ever considered would be a problem for the majority of our customers.

So my question to you is: why do you want to do this? Surely it is up to the developer of the derived class to determine whether or not the base class implementation is correct for the derived class or not. That's not up to you. And even if you did have some way to do that, what would stop the developer from simply saying

override void M() { base.M(); }

?

Can you explain what purpose you have for attempting to force this work upon the developers of your derived classes? Perhaps there is a better way to achieve what you want.

But more generally: I am not sure that your hierarchy is sensibly designed in the first place. When I see a method GiveBonus on an Employee, I assume that this means that "an employee can give a bonus", not "an employee can receive a bonus". Surely a manager gives a bonus and an employee receives a bonus. I think you might be making the employee hierarchy do too much.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • This is a case for the creation of a FAQ page, serving both questions, and merging the answers into that page. – John Saunders Jan 22 '10 at 17:44
  • 1
    @John Saunders: sounds like volunteering to me. Go for it. :-) – Eric Lippert Jan 22 '10 at 18:05
  • @Eric: you're right. I _was_ volunteering you! :-) Besides we don't have a mechanism for tag-specific FAQ pages. I was advocating such FAQ pages. The authors of the pages becomes the subsequent question. I'll try to find and revive the topic on meta. – John Saunders Jan 22 '10 at 18:38
  • @Eric: See http://meta.stackexchange.com/questions/12182/when-is-a-duplicate-question-not-a-duplicate/12197#12197, http://meta.stackexchange.com/questions/2038/should-you-gain-rep-for-asking-a-duplicate-question/2048#2048, and http://meta.stackexchange.com/questions/7441/can-and-should-more-be-done-to-encourage-users-to-search-first-and-ask-only-if/7473#7473. – John Saunders Jan 22 '10 at 18:52
  • @Eric: Better still, http://meta.stackexchange.com/questions/1195/create-a-tag-homepage-faq and http://meta.stackexchange.com/questions/21727/topic-tag-specific-faq-pages – John Saunders Jan 22 '10 at 18:56
  • @BrettCaswell: I strongly encourage you to provide an answer that you like better, since apparently you have strong feelings on this matter and have given it some thought. I am somewhat confused by your claims about VB; an answer would be a good place to describe them at length, to make sure that they are clear to the reader. – Eric Lippert Oct 02 '14 at 15:58
  • 2
    Ah, no, I was incorrect on a couple of things; I reacted on "The C# language does not have a mechanism for ..." without fully understanding the context of the question and explaination. I came to this Q&A based on a simple search of 'C# MustInherit', so that was the pretext to my confusion and objection.. C# does have the MustOveride equivalent (mechanism), an abstract method on an abstract class.. http://msdn.microsoft.com/en-us/library/k535acbf(v=vs.71).aspx .. of course, that wasn't the point of dicussion here.. – Brett Caswell Oct 02 '14 at 17:12
  • 9
    Equals sounds like a good candidate for such a forced overriding. I don't want people to forget that they need to override equal, because otherwise the extra fields that their derived class adds won't be compared. – Clément Jul 09 '15 at 18:33
  • 5
    (I know this is an old question - but its current for me) as Clement says Equals is a sensible use case. Clone would be another - there are more. Yes it is the derived class designers choice as to whether the base implementation does the job, and there isn't anything- and does not need to be anything - to stop them calling the base implementation as you show. This though is a deliberate conscious decision by the derived class developer. What the must-override mechanism would do is ensure that they have not forgotten to consider whether an override is required. – ROX May 26 '17 at 17:17
  • 5
    @ROX: I see your point. We also see the "dual" of this error frequently: someone overrides a method and *forgets* to call the base class version of the method, even though they have not replicated its logic adequately in the override. Rather than a *must-override*, I'd like to see a way to expression *must-call-base-if-you-override*. – Eric Lippert May 26 '17 at 17:44
14

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.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
14

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.

Community
  • 1
  • 1
Vincent
  • 3,656
  • 1
  • 23
  • 32
13

Declare the class Employee as abstract, the class SalesPerson as concrete (non-abstract), and provide an implementation of GiveBonus() that throws a runtime exception with a message like "Must be implemented by subclasses" for any types or cases which the provided code is not supposed to cover. It's an old Smalltalk practice. I have used it in Java code.

if (GetType() != typeof(SalesPerson)) 
{
    throw new NotImplementedException("Please override in subclasses");
}

// ...proceed with giving SalesPerson a bonus
Jirka Hanika
  • 13,301
  • 3
  • 46
  • 75
JuanZe
  • 8,007
  • 44
  • 58
10

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.

Robert Rossney
  • 94,622
  • 24
  • 146
  • 218
6

A WA may be using an "Interface" so you define one like IBonusGiver { void GiveBonus(); } An then, instead of the abstract method and the overrides, you implement in all your classes this new interface. e.g. PTSalesPerson : SalesPerson, IBonusGiver forcing a new implementation in each class.

mind_overflow
  • 91
  • 1
  • 2
  • 1
    This is the REAL answer to the original question, he wants something that FORCES the derived classes to implement a method – Hannish Sep 05 '16 at 15:07
  • @Hannish but what if the base and derived class shouldn't be abstract and both have to have the same behaviour? The base class implements this cool new interface and there's no chance to force anything to the derived class. I've to implement Clone and need to force this override. Okay there's a way to create only abstract or sealed classes. Every abstract class contains an abstract method that must be overriden in derived classes. But: Base contains abstract `InnerClone`. Sub overrides sealed and contains abstract `InnerClone2`. UnitTest for only abstract or sealed. That's not nice. – Sebastian Schumann Dec 15 '16 at 10:20
  • @Verarind what you describe is an hypothetical scenario which I think is out of the scope of the original question. In case of doubt, KISS (keep it simple and stupid). – Hannish Dec 15 '16 at 14:46
  • 1
    I'm pretty sure that this is not a hypothetical case because I'm currently working on exactly that clone method. I created a `MustInheritAttribute` interface and check that in a post build event. – Sebastian Schumann Dec 15 '16 at 14:56
  • 1
    This doesn't accomplish what OP requested, because SalesPerson also is an IBonusGiver. – ToolmakerSteve Oct 16 '21 at 04:32
2

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
   }
}
Dave Cousineau
  • 12,154
  • 8
  • 64
  • 80
2

You can't using the setup you described. PTSalesPerson will already have an implementation of GiveBonus because it inherits from SalesPerson.

hackerhasid
  • 11,699
  • 10
  • 42
  • 60
1

If you aren't going to create a SalesPerson instance directly, then the simplest thing to do would be to make SalesPerson abstract and that would force any child classes to implement it instead (or be abstract themselves).

If there is some logic in that method common to all SalesPeople, then you could implement GiveBonus on SalesPerson as a template method. Which calls some abstract method required in any subclasses:

Which ever way you decide, the only way to force an implementation in a child class is to make the base class abstract.

Lee
  • 142,018
  • 20
  • 234
  • 287
1

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.

FallenAvatar
  • 4,079
  • 1
  • 21
  • 24
0

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

0

This is pretty old, but we have a somewhat similar situation. The base class loads a configuration file and sets up base class defaults. However, the configuration file could also contain default values for inherited classes.

This is how we got the combined functionality.

Base class methods

private void processConfigurationFile()
{
    // Load and process the configuration file
    // which happens to be an xml file.
    var xmlDoc = new XmlDocument();
    xmlDoc.Load(configurationPath);

    // This method is abstract which will force
    // the inherited class to override it.
    processConfigurationFile(xmlDoc);
}

protected abstract void processConfigurationFile(XmlDocument document);
j2associates
  • 1,115
  • 10
  • 19
0

Okay, I know this post is old, however, I have recently needed to look this answer up, so for anyone else looking for this: (I am using VS 2012 .net 4.5, so not sure about older versions)

I created an abstract class, and used override on both child classes:

public abstract class Person
{
    public string Name { get; protected set; }
    public abstract void GiveName(string inName);
}

public class Employee : Person
{
    public override void GiveName(string inName)
    {
        Name = inName;
    }
}

public class SalesPerson:Employee
{
    public override void GiveName(string inName)
    {
        Name = "Sales: "+inName;
    }
}

Testing:

SalesPerson x = new SalesPerson();
x.GiveName("Mark"); //Name="Sales: Mark"
Employee e = x;
e.GiveName("Mark"); //Name="Sales: Mark"
Employee m = new Employee();
m.GiveName("Mark"); //Name="Mark"
Arkaine80
  • 186
  • 1
  • 10
0

I very much hope my answer will help some people confused by this issue.

Bear with me, but I'll try to re-summarise what is being asked, just to ensure that I am answering the right question. Then I'll give the answer!

I think the essence of the question is: How do I declare a method in an abstract class so that is has an implementation but still requires a derived class to override the method?

C# doesn't appear to support this. If you declare the method 'abstract', it is not permitted to have an implementation (body). But if you declare it 'virtual', a derived class is not forced to override it. C# deosn't allow a method to be marked as both abstract and virtual.

I believe there are many situations where you wish to do this (what is being asked).

The way to solve this riddle is as follows: Declare two methods! One of them is marked 'abstract'; the other is marked 'virtual' and calls the first one somewhere in its body.

This way, the derived class is forced to override the abstract method, but the (partial) implementation in the virtual method can be safely inherited.

So, for example, the Employee method GiveBonus might be declared thus:

public abstract decimal ComputeBonus();
public virtual void GiveBonus() { 
    decimal amount = ComputeBonus();
    if (amount > 0.0) PostBonus(amount);
}

I'll leave the details of PostBonus to the imagination, but the beauty of this approach is that derived classes are forced to override ComputeBonus, yet GiveBonus benefits from the partial implementation provided in the base class. HTH

debater
  • 466
  • 6
  • 11
  • I've just contradicted my own advice! In an abstract method where the partial implementation in the base class would have been trivial, I've left the method abstract and just added a comment to tell implementors what they are expected to do. For every rule, ... – debater Sep 13 '17 at 13:50
  • I've been voted down on this answer and I'd like to know why, please? Despite my previous comment, I think my answer is good. – debater Aug 13 '18 at 15:43