2009-05-04 1 views
2

Предположим, у меня есть абстрактный родительский класс, называемый «форма», и что существует несколько подклассов (треугольник, квадрат, круг ...). Я хочу определить абстрактный метод в родительском классе «shape», который должны реализовать все подклассы, назовем его «draw». Поэтому все подклассы формы должны предоставлять метод draw(). Но метод рисования принимает параметр типа «Stencil», и не каждый подкласс формы может использовать только какой-либо трафарет ...Возможно ли иметь специализированные параметры в переопределенных методах?

Итак, существует один абстрактный класс «форма», несколько подклассов формы и несколько трафаретов. Мне нужен метод рисования, определенный в классе формы. Квадрат может использовать Stencil1, и круг может использовать Stencil2.

Я предполагаю, что дженерики будут делать трюк, но я не уверен. Каждый подкласс формы должен определять метод draw с помощью определенного шаблона, потому что эти классы также используются другими классами, а компилятор должен заставить всех программистов вызывать методы рисования с помощью трафарета, поддерживаемого этим классом. Мы не можем определить абстрактный метод, такой как «публичная абстрактная пустота рисования (Stencil s)», потому что тогда программист мог передать любой трафарет в квадратный класс, тогда как квадратный класс поддерживает только «Stencil1»

Любые идеи?

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

+0

Кроме того, что класс формы заботится, потому что, как вы заявили, «компилятор должен заставить все программист вызывать методы нарисованных с помощью трафарета, который поддерживается этим классом» – cgp

+0

Нет, класс формы не забота; это другое использование различных классов формы, которые заботятся. – user85116

ответ

7
public abstract class Shape<S extends Stencil> 
{ 
    public abstract void draw(S stencil); 
} 

public class Square extends Shape<Stencil1> 
{ 
    public void draw(Stencil1 stencil) 
    { 
    stencil.letsdo(); 
    stencil.some(); 
    stencil.drawing(); 
    } 
} 

public class Circle extends Shape<Stencil2> 
{ 
    public void draw(Stencil2 stencil) 
    { 
     stencil.some(); 
     stencil.more(); 
     stencil.drawing(); 
    } 
} 
+1

не будет ли метод подписи подписи не согласен с сигнатурой метода абстрактного метода рисования? –

+0

Нет, на самом деле. Я просто протестировал это в Eclipse, чтобы быть уверенным, и он отлично работает. –

+0

№ draw() определяется как S, который должен быть типа Stencil или подкласса. В Square/Circle вы просто указываете подклассу Stencil, которую хотите использовать, - поскольку она все еще является Stencil, она не конфликтует с сигнатурой метода суперкласса. – alasdairg

0

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

  • Создать набор абстрактных трафаретов. В частности, если вы думаете, что можете их сгруппировать. Поэтому, если у вас будет несколько «квадратных» трафаретов, создайте абстрактный тип SquareStencil и выведите из него конкретные экземпляры. Вы даже можете создать их как подмножество абстрактного класса Stencils.
  • Перегрузка метода ничьей. Нет необходимости, чтобы он был общим. Пусть компилятор поможет вам, выбрав правильный метод для задания.
+0

Если бы я перегрузился, это ухудшило бы проблему, не так ли? Мне не нужны несколько вариантов ничьей; Я хочу одну версию, которая принимает только правильный трафарет для этого класса. – user85116

1

Я думаю, вам, вероятно, следует пересмотреть свой первоначальный дизайн.

Конечно, вы, , можете обойти это с помощью instanceof и т. Д. Однако это приведет к очень запутанному API (если это то, для чего вы его используете).

+0

Я уверен, что дизайн звучит запутанно из моего описания, но это не так уж плохо – user85116

0

Определить абстракцию трафарета и позволить конструктору подкласса решить, какой класс трафарета использовать.

private Stencil s; 

public void draw(){ 
    privateDraw(s) 
} 

private abstract void privateDraw(Stencil s); 
Смежные вопросы