Самый специфический подкласс для объекта Java? - PullRequest
2 голосов
/ 17 мая 2009

У меня есть два класса A и B, где B является подклассом A, а A не является абстрактным. Поэтому я могу иметь объекты, которые являются экземплярами A и объекты, которые являются экземплярами B (и, следовательно, A).

Как я могу различить объекты, которые являются только экземпляром A?

Конечно, я могу написать что-то вроде «object instaceof A &&! (Экземпляр объекта B)», но это очень плохой дизайн, так как мне придется менять код каждый раз, когда я добавляю новые подклассы в A. Лучшие альтернативы

Ответы [ 6 ]

7 голосов
/ 17 мая 2009
object.getClass() == A.class
5 голосов
/ 17 мая 2009

Почему вы хотите, чтобы их различали? Обычно это противоположность ОО. У вас есть разные экземпляры, которые вам не нужно различать, потому что разные реализации все делают правильно.

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

Я бы instanceOf и getClass уже рассмотрели плохой стиль, если он используется без уважительной причины

2 голосов
/ 17 мая 2009

Я думаю, что вы говорите:

public class A {
}

public class B extends A {
}

позже в коде:

A apple = new A();
B banana = new B();

Вот несколько вариантов, которые могут оказаться полезными:

if (apple.getClass() == A.class) { // Found an A }
if (banana.getClass() == A.class) { // This is not an A, won't get here. }
if (apple instanceof A) { // This is definitely an A }
if ((apple instanceof A) && (!(apple instanceof B))) { // It's an A but not a B }

Что касается последнего варианта, вы пишете следующее:

Конечно, я могу написать что-то вроде "объект intaceof A &&! (объект экземпляр б) "но это очень плохой дизайн, так как мне нужно изменить код каждый раз, когда я добавляю новый подклассы для А. Лучшие альтернативы?

Полиморфизм почти всегда помогает нам здесь. Ваша точка зрения об изменении кода каждый раз, когда вы добавляете подкласс, является именно тем симптомом, который вы должны признать стандартным развитием объектно-ориентированного проектирования. Подумайте о поведении, которое вы пытаетесь произвести. Можете ли вы вставить это в сам класс, а не делегировать его внешнему поставщику, который должен определить, над каким классом он работает в настоящее время?

Без дополнительной информации я не могу дать слишком много указаний, но вот довольно простой пример:

// Instead of this
if (apple.isClassA()) { // run class A code
} else if (apple.isClassB()) { // run class B code
// And so forth
}

Измените дизайн, чтобы он стал более похожим на:

public class A {
    public void executeCommand() { 
        // run class A code 
        // This method knows that it's definitely an A, not a B
    }
}

public class B extends A {
    public void executeCommand() { 
        // run class B code 
        // This method knows that it's a B (and, therefore, an A as well).
    }
}

Где позже в коде выполнения вы заменяете предыдущий тест if следующим:

apple.executeCommand();
banana.executeCommand();

По общему признанию, это почти тривиальный объектно-ориентированный обзор проекта, но он может расшатать что-то и помочь вам с проблемой подклассов.

2 голосов
/ 17 мая 2009

Лучше сделать тест методом результата

class A {
   public boolean isSomeTest() {
      return true;
   }
}
class B extends A {
   public boolean isSomeTest() {
      return false;
   }
}

Тогда, если вы добавите C, который расширяет A, вы можете позволить ему возвращать true или false.

Имя isSomeTest должно прояснить, что должно означать возвращение true или false.

2 голосов
/ 17 мая 2009

Разве это не показывает, что B на самом деле не A? Я не совсем уверен, что вы должны попасть в эту ситуацию? Возможно, вы могли бы улучшить свой дизайн ??

0 голосов
/ 17 мая 2009

Используйте метод getClass объекта для свойства класса:

if(someObject.getClass() == A.class){
   //some code
}
...