2010-04-13 2 views
2
interface ICanvasTool 
{ 
    void Motion(Point newLocation); 
    void Tick(); 
} 

abstract class CanvasTool_BaseDraw : ICanvasTool 
{ 
    protected abstract void PaintAt(Point location); 

    public override void Motion(Point newLocation) 
    { 
     // implementation 
    } 
} 

class CanvasTool_Spray : CanvasTool_BaseDraw 
{ 
    protected abstract void PaintAt(Point location) 
    { 
     // implementation 
    } 

    public override void Tick() 
    { 
     // implementation 
    } 
} 

Это не скомпилировано. Я мог бы добавить абстрактный метод «Tick_Implementation» в CanvasTool_BaseDraw, а затем реализовать ICanvasTool.Tick в CanvasTool_BaseDraw с помощью однострочного интерфейса, который просто вызывает Tick_Implementation. Это рекомендуемое решение?Мой абстрактный класс реализует интерфейс, но не реализует некоторые из его методов. Как мне его скомпилировать?

+0

Я не уверен, что вы подразумеваете под «обходным путем», поскольку вы используете интерфейс. Интерфейс - это контракт, и поэтому любой тип, который реализует интерфейс, ДОЛЖЕН придерживаться этого контракта. Это принудительное выполнение компилятором выполняется таким образом, чтобы вызывающие пользователи вашего класса могли знать, что любой тип, реализующий ICanvasTool, имеет эти два метода. – Josh

+0

Да, я * хочу * компилятор, чтобы гарантировать, что любой неабстрактный потомок интерфейса реализует все это. Я просто не хочу, чтобы это имело место для * абстрактных * потомков. –

+0

BTW, Java делает это по-моему. См. Http://stackoverflow.com/questions/197893 –

ответ

6

Способ заключается в том, чтобы добавить реферат void Tick() к CanvasTool_BaseDraw и переопределить его в CanvasTool_Spray.

Не каждый язык программирования делает это таким образом. В Java вам не нужно добавлять абстрактный метод для каждого метода в интерфейсе (интерфейсах), который вы реализуете. В этом случае ваш код будет компилироваться.

+0

Спасибо. Кажется, что бит счетчик интуитивно понятен, но он работает. –

4

У вас есть несколько вещей, вперемешку ..

движение должно быть виртуальным в вашем базовый классе, так что он может быть переопределен в дочерних классах. Ваш класс child должен сделать PaintAt переопределением вместо абстрактного. Базовый класс должен реализовать Tick как абстрактный метод.

interface ICanvasTool 
{ 
    void Motion(Point newLocation); 
    void Tick(); 
} 

abstract class CanvasTool_BaseDraw : ICanvasTool 
{ 
    protected abstract void PaintAt(Point location); 

    public virtual void Motion(Point newLocation) 
    { 
     // implementation 
    } 

    public abstract void Tick(); 
} 

class CanvasTool_Spray : CanvasTool_BaseDraw 
{ 
    protected override void PaintAt(Point location) 
    { 
     // implementation 
    } 

    public override void Tick() 
    { 
     // implementation 
    } 
} 
+0

Да, первые две ошибки были результатом нетерпеливого броска кода-примера для SO. И ваше решение правильно. Благодарю. –

+0

Er, держитесь. Почему Motion должен быть виртуальным в CanvasTool_BaseDraw? Мне действительно не нужно позволять подклассам переопределять его. –

+0

Прошу прощения. Это не должно быть. Я просто предположил, что вы хотите, чтобы это было надёжным, поскольку это был базовый класс. Однако использование «переопределения» является незаконным, так как вы реализуете интерфейс, а не наследуете абстрактный класс или класс с помощью виртуального метода. – Krisc

0

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

+1

Да, но CanvasTool_BaseDraw - это * не * конкретный класс. –

1

Альтернативой не является описание интерфейса в объявлении базовых классов. Каждый производный класс должен отображать ICanvasTool в своем объявлении, если он хочет реализовать интерфейс, а затем он несет полную ответственность за реализацию остальной части интерфейса. Один недостаток, который я вижу, заключается в том, что вы не можете явно реализовать методы интерфейса в базовом классе (то есть без ICanvasTool: Motion), но в остальном это довольно низкая служебная версия.

public interface ICanvasTool 
{ 
    void Motion(Point newLocation); 
    void Tick(); 
} 

public abstract class CanvasTool_BaseDraw 
{ 
    public void Motion(Point newLocation) 
    { 
     //some implementation 
    } 
} 

public class CanvasTool_Spray : CanvasTool_BaseDraw, ICanvasTool 
{ 
    public void Tick() 
    { 
     //some implementation 
    } 
} 

Примечание: Я оставил PaintAt, потому что это не было необходимым для примера.

Смежные вопросы