Как принудительно переопределить метод в потомке, не имея абстрактного базового класса? - PullRequest
42 голосов
/ 22 января 2010

Заголовок вопроса, кажется, немного сбивает с толку, но я постараюсь прояснить мой вопрос здесь.

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

    }
}

Пожалуйста, не пытайтесь понять весь код. Я обобщаю его.

  1. Сотрудник - это класс Abstract, у которого есть абстрактный метод GiveBonus
  2. SalesPerson является производным от Employee. SalesPerson должен дать определение абстрактному методу GiveBonus. ( SalesPerson не может быть абстрактным )
  3. PTSalesPerson является производным от SalesPerson.

Теперь мой вопрос: как я могу заставить PTSalesPerson иметь собственную реализацию GiveBonus.

Ответы [ 14 ]

0 голосов
/ 05 июля 2017

Я очень надеюсь, что мой ответ поможет некоторым людям, смущенным этой проблемой.

Терпите меня, но я постараюсь подвести итог тому, что спрашивают, просто чтобы убедиться, что я отвечаю на правильный вопрос. Тогда я дам ответ!

Я думаю, что суть вопроса такова: как мне объявить метод в абстрактном классе, чтобы он имел реализацию, но все еще требует, чтобы производный класс переопределил метод?

C # не поддерживает это. Если вы объявляете метод «абстрактным», ему не разрешается иметь реализацию (тело). Но если вы объявите его «виртуальным», производный класс не будет вынужден переопределять его. C # не позволяет помечать метод как абстрактный и виртуальный.

Я полагаю, что есть много ситуаций, когда вы хотите сделать это (о чем спрашивают).

Способ решения этой загадки заключается в следующем: Объявите два метода! Один из них помечен как «абстрактный»; другой помечается как «виртуальный» и называет первый где-то в своем теле.

Таким образом, производный класс вынужден переопределять абстрактный метод, но (частичная) реализация в виртуальном методе может быть безопасно унаследована.

Так, например, метод GiveBonus для Employee может быть объявлен так:

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

Я оставлю детали PostBonus для воображения, но прелесть этого подхода в том, что производные классы вынуждены переопределять ComputeBonus, однако GiveBonus выигрывает от частичной реализации, предоставляемой в базовом классе. НТН

0 голосов
/ 08 сентября 2016

Хорошо, я знаю, что это сообщение старое, однако недавно мне нужно было найти этот ответ, так что для всех, кто ищет это: (я использую VS 2012 .net 4.5, поэтому не уверен насчет более старых версий)

Я создал абстрактный класс и использовал переопределение в обоих дочерних классах:

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

Тестирование:

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"
0 голосов
/ 14 февраля 2014

Это довольно старый, но у нас несколько похожая ситуация. Базовый класс загружает файл конфигурации и устанавливает значения по умолчанию для базового класса. Однако файл конфигурации также может содержать значения по умолчанию для унаследованных классов.

Вот как мы получили объединенную функциональность.

Методы базового класса

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);
0 голосов
/ 22 января 2010

Вы всегда можете заставить реализацию SalesPerson генерировать исключение NotImplementedException. : V Но по контракту, нет, вы не можете этого сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...