Почему абстрактный класс должен реализовывать абстрактный метод абстрактного базового класса? - PullRequest
2 голосов
/ 17 июля 2010

В следующем примере класс Derived реализует абстрактный метод method из класса Main.Но я не могу придумать причину для заполнения тела метода в абстрактной Derived реализации класса.Конечно, я должен реализовывать абстрактные методы только в реальных классах.

Так как же мне избежать этого?Что еще я могу сделать?

abstract class Main
{
    public abstract void method();
}
abstract class Derived : Main
{
    public override void method()
    { 
    }
}

class RealClass : Derived
{

}

Ответы [ 3 ]

9 голосов
/ 17 июля 2010

Обычно, если кто-то указал, что у абстрактного класса есть абстрактный метод, это либо потому, что этот класс зависит от того или иного метода от того или иного метода, либо потому, что он является частью ожидаемого API, что для него не имеет смысла. родительский класс для реализации в это время. В любом случае, должна быть реализацией, как только вы попадете в неабстрактную реализацию класса.

Обратите также внимание, что если вы реализуете интерфейс , вы должны указать, как этот интерфейс будет реализован, даже если вы просто вызываете абстрактное членство и передаете ответственность подклассу

public interface IPet {string GetNoise(); int CountLegs(); void Walk();}
public abstract class Pet : IPet
{
    public string Name {get; set;}
    public abstract string GetNoise(); // These must be here
    public abstract int CountLegs();
    public abstract void Walk();
}

Когда дело доходит до реализации подкласса, у вас есть несколько вариантов в зависимости от обстоятельств. Если ваша реализация сама является абстрактным классом, вам не нужно реализовывать абстрактный метод.

public abstract class Quadruped : Pet
{
    public override int CountLegs () { return 4; }
}

Если ваша реализация неабстрактная, но стандартная причина для рассматриваемого метода действительно не применима в ваших обстоятельствах, вы можете сделать неоперативный метод (в случае пустых методов) или вернуть несколько фиктивных значение или даже бросить NotImplementedException, чтобы указать, что метод никогда не должен был вызываться в первую очередь.

public class Fish : Pet
{
    public override string GetNoise() {return "";} // dummy value: fish don't make noise
    public override int CountLegs() {return 0;}
    public override void Walk() {} // No-op
    // public override void Walk() { throw new NotImplementedException("Fish can't walk"); }
}

Это отвечает на ваш вопрос?

4 голосов
/ 17 июля 2010

Если в Derived нет реализации method, тогда вы можете просто сделать Derived абстрактным:

abstract class Derived : Main
{
}

class RealClass : Derived
{
    public override void method() { ... }
}

РЕДАКТИРОВАТЬ: Чтобы уточнить комментарии - если нет значимой реализации абстрактного метода в подклассе, то не нужно предоставлять. Это, однако, потребует, чтобы производный класс сам был абстрактным, и реализация должна быть предоставлена ​​где-то в цепочке классов-потомков некоторого конкретного подкласса. Я не говорю, что вы должны оставить реализацию method пустой, как в вопросе, но вы скорее удалите переопределение в Derived и отметите класс как абстрактный. Это заставляет RealClass предоставлять реализацию (или саму помеченную как абстрактную).

0 голосов
/ 17 июля 2010

Все неабстрактные классы-потомки должны обеспечивать конкретные реализации абстрактных методов.Если вы не предоставите реализацию, то невозможно вызвать этот метод.

Если у некоторых конкретных классов нет очевидной правильной реализации абстрактного метода, значит, ваш объектный дизайн неверен.Может быть, у вас должен быть абстрактный класс с некоторыми абстрактными методами (но не со всеми).Этот класс может иметь как абстрактного потомка, так и некоторых конкретных потомков.

...