Несколько производных абстрактных классов? - PullRequest
7 голосов
/ 30 июня 2011

Мне нужно создать систему управления курсами с категориями курсов:

Cooking, sewing and writing courses

cooking и writing каждый имеет 2 курса (итальянский, морепродукты, творческое письмо и деловое письмо). Это создает производное резюме:

abstract course -> abstract cooking -> concrete seafood

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

Можно ли это сделать в C #? Если я делаю абстрактные методы производного абстрактного класса, Visual Studio говорит, что они скрывают абстрактный базовый класс, а затем в методах конкретного класса возникают ошибки, говорящие о том, что базовый класс должен быть абстрактным (он есть, но не должен регистрироваться). Я искал ответ. Я знаю, что одиночное наследование используется в C #, но наследование ведет вниз по цепочке. Какой лучший ответ?

Вот фрагмент кода - надеюсь, он прояснит проблему:

public abstract class Course
{
    public abstract void AddStudent(StudentName sn, int f);
    public abstract decimal CalculateIncome();
}

public abstract class WritingCourse : Course
{
    public void AddStudent(StudentName sn, int f)
    {
     //Add student
    }
    public abstract decimal CalculateIncome(); // can only be claculated in concrete
}

public class BusinessWritCourse : WritingCourse
{
    public void AddStudent(StudentName sn, int f):
    base(sn, false){}

    public decimal CalculateIncome()
    {
       return //do stuff
    }
}

public class SewingCourse : Course
{
    public override void AddStudent(StudentName sn, int f)
    {
        //do stuff
    }

    public override decimal CalculateIncome()
    {
       return //do stuff
    }
}

Ответы [ 4 ]

7 голосов
/ 30 июня 2011

если я сделаю производный абстрактный класс абстрактные методы Visual Studio говорит они скрывают абстрактный базовый класс и тогда конкретные методы класса имеют ошибки говорят, что базовый класс должен быть аннотация (есть, но не должна регистрироваться)

Если у вас есть базовый класс 'A', у которого есть абстрактный метод 'b ()', вам не нужно снова объявлять 'b ()' как абстрактный в B: A, чтобы C: B переопределил его, просто не используйте это. Даже если вы переопределите метод 'b ()' в классе B, вы можете снова переопределить его в классе 'c ()' (и даже использовать base. (); Чтобы выполнить реализацию B.

Некий код:

public abstract class A{
    public abstract void b();
}

public class B : A{
    public override void b() { //do stuff }; //overrides b from a
    public virtual void c() { //do stuff }; //creates an implemented method c in B that can be overriden by childs.
    public void d() { //do stuff};
}

public class C : B{
    public override void b() { //do stuff}; //overrides b from A, works!
    public override void c() {//do stuff}; //overrides c from B, works!
    public override void d() {//do stuff}; //doesn't work since d from B isn't abstract or virtual (hides it)
    public new void d() {//do stuff}; //works, hides d, but when you use inheritance this method will not be called, instead B's d() method will be called, only if you see C as  the specific class C this will work
}

Также, чтобы уточнить: методы, объявленные абстрактными, должны быть переопределены (как в интерфейсе, и только прямым потомком класса, объявляющего абстрактный метод). Методы, объявленные виртуальными, могут быть переопределены, но не обязательно.

4 голосов
/ 30 июня 2011

Я думаю, что такого рода проблемы лучше решать с помощью интерфейсов, а не абстрактных классов: Пример:

//
interface IInterface1
{
    void SameMethod();
}

interface IInterface2
{
    void SameMethod();
}


class TestClass : IInterface1, IInterface2
{
    void IInterface1.SameMethod()
    {
        // do one thing for Interface 1
    }

    void IInterface2.SameMethod()
    {
        // do something elsefor Interface 2
    }
}

class Program
{
    static void Main(string[] args)
    {
        TestClass test = new TestClass();

        IInterface1 i1 = test;
        i1.SameMethod(); // will call IInterface1.SameMethod()

        IInterface2 i2 = test;
        i2.SameMethod(); // will call IInterface2.SameMethod()

    }
}
1 голос
/ 01 февраля 2017
public class StudentName
{ }

public abstract class Course
{
    public abstract void AddStudent(StudentName sn, int f);
    public abstract decimal CalculateIncome();
}

public abstract class WritingCourse : Course
{
    override public void AddStudent(StudentName sn, int f)
    {
        //Add student
    }
    override public abstract decimal CalculateIncome(); // can only be claculated in concrete
}

public class BusinessWritCourse : WritingCourse
{
    override public void AddStudent(StudentName sn, int f)
    { base.AddStudent(sn, 0); }

    override public decimal CalculateIncome()
    {
        return (decimal)3.4;//do stuff
    }
}

public class SewingCourse : Course
{
    public override void AddStudent(StudentName sn, int f)
    {
        //do stuff
    }

    public override decimal CalculateIncome()
    {
        return (decimal)10; //do stuff
    }
}

class Program
{
    static void Main(string[] args)
    {

    }
}
0 голосов
/ 30 июня 2011

Если я правильно понимаю, я думаю, что вы хотите использовать ключевое слово «virtual» для абстрактных методов, которые вы хотите переопределить?

Если вы говорите об ошибке, которая говорит что-то вроде: «какой-то метод скрывает унаследованный член, добавьте новое ключевое слово, если было скрыто намерение», тогда виртуальный в базовом методе и переопределение в методе наследования сделают:

public abstract class BaseClass
{
    public virtual void SomeMethod()
    {
    }
}


public abstract class InheritingClass : BaseClass
{
    public override void SomeMethod()
    {
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...