Как проектировать, когда существует только один подкласс, который нужно указать с помощью полиморфизма? - PullRequest
0 голосов
/ 13 июня 2019

Учитывая базовый класс База , то есть A , B , C расширяется База . Если есть определенный метод m () только в C . Чтобы вызвать m () , вы должны сначала определить, является ли данный класс типом C , одним из способов является использование:

otherMethod(Base b){
  if(b instanceof C) 
    b.m();
}

Но я бы хотел использовать:

otherMethod(Base b){
  b.m();
}

Это означает, что мне нужно подтянуть метод m () до суперкласса Base и реализовать его только в классе C . Но m () не имеет отношения к классу A и B и не должно принадлежать им. Это не интуитивно понятно для читабельности кода. Так есть ли лучший дизайн этого случая для использования полиморфизма и без необоснованной позиции метода?

Ответы [ 5 ]

0 голосов
/ 14 июня 2019

Не заражайте дизайн дальше, чем добавляя Base.visit(IVisitor v) {v.visit(this);}

interface IVisitor {
  void visit(Base b);
}

Затем напишите нужный вам IVisitor (здесь с экземпляром C). Конечно, вы можете просто использовать Consumer вместо своего собственногоинтерфейс посетителя.Я просто хотел быть ясным.

0 голосов
/ 14 июня 2019

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

Предполагая Collection<Shape> shapes:

shapes.stream()
      .filter(s -> s instanceof C)
      .forEach(c -> ((C)c).m());

пь. Вы никогда не должны объявлять поведение (то есть методы) в классах или интерфейсах, которые не имеют к этому никакого отношения. В примере с ernest_k не указывайте get(int) в интерфейсе Collection только потому, что List использует его. Это сохраняет структуру класса чистой и понятной. Вместо этого измените использование структуры класса, либо сложным способом (с проверкой типов и приведением типов), либо путем разделения разных подклассов в разных коллекциях (чтобы вам не приходилось проверять типы).

Если у вас было это:

Collection<A> justA;
Collection<B> justB;
Collection<C> justC;

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

0 голосов
/ 13 июня 2019

Ответ на этот вопрос может вам чем-то помочь: Есть ли решение для пустых методов в подклассе?

По сути, это предполагает, что вы создаете пустой метод всуперкласс, затем внедрите его в подкласс (ы), как считаете нужным.Тем не менее, он предупреждает, что такая практика должна быть исключением, а не правилом, поэтому использование instanceof может оказаться более практичным решением.

0 голосов
/ 13 июня 2019

Другим вариантом является использование переопределяющих методов. При вызове otherMethod () для объекта Base он вызовет doThings (), определенный в Base, если только он не является экземпляром C, который перегружен doThings ().

public class Base {

   public void doThings() {
       // nothing happens
   }

   public void otherMethod() {
       doThings(); // will call method above if instance is Base object, will call method below if C object
   }
}

class C extends Base {

   public void doThings() {
       System.out.println( "Things actually get done" );
   }
}
0 голосов
/ 13 июня 2019

Если у класса C есть какой-либо конкретный метод, он не должен быть частью класса Base.Чтобы вызвать метод m(), вам нужно проверить тип экземпляра с помощью оператора instanceof, а затем привести класс Base к C, а затем вызвать метод m(), как показано ниже

otherMethod(Base base){
  If(base instanceof C){
    C c= (C) base;
    c.m();
  }
}

Кроме того, поскольку другие уже приводили пример Collection и List, если вашему классу C требуется определенный метод, вы должны создать один interface, скажем, его имя Child, которое должнорасширить интерфейс Base.Другие 2 класса должны реализовывать интерфейс Base.И класс C должен реализовывать интерфейс Child.

Теперь, когда вы разрабатываете интерфейс Base, вы определенно не будете знать, какие конкретные методы могут реализовать другие классы.Следовательно, вам не следует также вызывать какой-либо конкретный метод в вашем другом методе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...