Подтвердить что ты не робот

Расширение интерфейса для абстрактного класса

У меня есть интерфейс (перемещение), который должен перемещать некоторые фигуры.

interface Move { move(); }
abstract class Shape : Move

class Circle : Shape
class Square : Shape
class Triangle : Shape

Я сомневаюсь, что у меня должен быть интерфейс, который перемещает Shapes, но только Circle и Triangle должны быть перемещены, так как я могу "удалить" интерфейс с Square? Должен ли я удалить интерфейс из Shape и добавить его вручную в Circle and Triangle? Я немного смущен этим. Надеюсь, кто-то может мне помочь.

4b9b3361

Ответ 1

Вы должны настроить свои классы следующим образом:

interface IMovable { move(); } 
abstract class Shape : { } 

class Circle : Shape, IMovable { } 
class Square : Shape { } 
class Triangle : Shape, IMovable { } 

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

Ответ 2

Вы не можете удалить интерфейс из дерева наследования.

Каждой модели вам нужны два абстрактных класса - Shape и MovableShape.

interface IMove { move(); } 
abstract class Shape : {} 
abstract class MovableShape : IMove, Shape {} 

class Circle : MovableShape{}
class Square : Shape{}
class Triangle : MovableShape{}

Ответ 3

Вы должны больше познакомиться с идеями интерфейсов, классов и OO в целом. То, что вы пытаетесь сказать, следующее:

  • Каждая фигура может перемещаться.
  • Квадрат - это форма.
  • Но квадрат нельзя перемещать.

Обидно, что не имеет смысла. Поэтому вам нужно настроить дизайн вашего класса. Либо каждая фигура может быть перемещена, чтобы Shape (и Square) должен реализовать Move, или не каждая фигура может быть перемещена, а затем Shape не должен выполнять Move.

Ответ 4

Попробуйте следующее:

interface IMove { move(); }
abstract class Shape { }

class Circle : Shape, IMove { }
class Square : Shape { }
class Triangle : Shape, IMove { }

Ответ 5

Другим вариантом может быть просто реализовать метод IMove.Move в классе Shape и по умолчанию поставить NotSupportedException.

public abstract class Shape : IMove 
{
     public virtual void Move()
     { 
         throw new NotSupportedException();
     }
}

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

Наконец, предположим, что есть куча фигур, которые перемещаются одинаково. Вы создали бы DefaultMovableShape вывод абстрактного класса Shape, который переопределяет виртуальный метод Shape.Move.

public abstract class DefaultMovableShape 
{
     public override void Move()
     {
           // Do stuff
     }
}

Ответ 6

Лучший ответ будет зависеть от того, какой будет прецедент и среда для этих классов. В рамках команды, разрабатывающей приложение или фреймворк, использование шаблонов проектирования, используемых этой командой, предпочтительнее поиска "идеального" решения, поскольку это облегчит для других принятие и поддержание вашего кода.

Как вы ожидаете, что эти классы будут использоваться и расширены, также важно. Ожидаете ли вы, что "Квадрат" должен быть движимым в будущем? Является ли подвижность формы всегда статической или может быть более полезной в качестве динамического атрибута? Имеет ли Move() какое-либо значение для классов, которые не являются фигурами? Если подвижность может быть полезна как динамический атрибут, рассмотрите это:

public abstract class Shape
{
     public bool isMovable()
     {
         return false;
     }

     public virtual void Move()
     { 
         if (!isMovable() {
             throw new NotSupportedException();
         } else {
             throw new BadSubclassException();
         }
     }
}

Затем ваши подклассы могут переопределять isMovable для обеспечения статического или динамического поведения и могут быть дополнительно модифицированы или подклассифицированы с течением времени, если в вашей документации ясно, что isMoveable всегда должен предшествовать вызову Move. Поведение по умолчанию должно основываться на ожиданиях других, которых вы ожидаете использовать в своем коде, в зависимости от того, как они реализовали связанные шаблоны проектирования.

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