Так что я довольно новичок в программировании в реальном мире (за пределами академических проектов) и наткнулся на множество постов, в которых говорится, что использование instanceof
- это плохая вещь, чтобы определить, к какому классу относится данный объект.
Моя ситуация такова, что у меня есть три класса, базовый класс продукта, один, который расширяет это и другой, который расширяет это. Все они хранятся в одной и той же таблице в базе данных, и у меня есть некоторый код, который должен использовать методы каждого для извлечения данных из них.
Как лучше всего обходить этот способ? Я прочитал некоторые вещи о полиморфизме, но я не могу найти примеры, которые решают проблему, которую я имею. Все они обычно переопределяют метод, который для меня не работает, так как мне нужно вытащить разные вещи из разных объектов.
Есть ли лучший способ сделать это, или я застрял с использованием instanceof
или какое-то отражение, чтобы получить поля, специфичные для объектов?
источник
instanceof
неверно; попытка найти класс объекта обычно является проблемой. Не всегда неправильно, но, вероятно, в вашем случае это так. Возможно, если вы расскажете нам, чего пытаетесь достичь, мы можем предложить решение с использованием полиморфизма.getSpecifics()
который реализуется по-разному для каждого, каждый из которых возвращает данные, специфичные для класса?Ответы:
Причиной
instanceof
разочарования является то, что это не ООП.У вызывающей стороны / пользователя объекта не должно быть никаких причин знать, к какому конкретному классу он относится, кроме какого типа переменная объявлена.
Если вам нужно другое поведение в подклассах, добавьте метод и реализуйте их по-разному.
источник
getSpecifics()
(или что-то подобное) для каждого класса, который будет возвращать специфику для каждого класса. Это лучший подход?List
. Я передаю это объекту, который берет любойIterable
. Теперь этот второй объект передает его третьему объекту, который принимает либоList
для оптимизации, либоIterable
гораздо медленнее. Второй не должен знать, что это список, но третий очень хотел бы знать. Разве третий объект не должен проверять, например, instanceof, может ли он применить оптимизацию? Посмотрите, например, гуаву,FluentIterable
которая делает именно это.instanceof
.instanceof
это не обязательно плохо, но на это нужно смотреть.Пример, где он работает правильно, находится в месте, где вы получаете коллекцию базового типа, а вам нужны только подтипы. Получение сетевых адресов
NetworkInterface.getNetworkInterfaces()
возвращает объекты NetworkInterface, которые имеют коллекцию объектов InetAddress, некоторые из которых - Inet4Address, а некоторые - Inet6Address. Если кто-то хочет отфильтровать коллекцию для объектов Inet4Address, необходимо использовать instanceof.В ситуации, описанной в исходном посте, есть базовый класс, который расширяет этот базовый класс, и нечто, расширяющее расширенный класс. Хотя это и не совсем информативно, в основе этого, похоже, лежит не совсем идеальный дизайн.
Когда вы возвращаете базовый класс, если для этого нет веской причины (обратная совместимость между спецификациями более ранней версии), вы не должны пытаться заглянуть в базовые типы. Если вам возвращают набор, вы знаете, что получаете набор. Позже разработчик может изменить свое мнение, чтобы вернуть более конкретный тип (SortedSet) или изменить базовый тип (HashSet на TreeSet), не нарушая ничего.
Пересмотрите свой дизайн того, как объекты структурированы и созданы, чтобы увидеть, можно ли создать лучшую модель класса, которая не требует различия типов.
источник
isOfType(SomeEnum.IPv4)
метод, может быть лучшим способом фильтрации таких качеств, чем проверка конкретного типа с помощьюinstanceof
. Что если вы захотите разделить ваш класс реализации IPv4 позже? Не то чтобы это всегда лучше, но это соображение.(o instanceof Serializable) || (o instanceof Externalizable)
. instanceof лучше альтернативыВы можете использовать метод getClass ().
Вы уверены, что вам нужно три разных класса? Может быть, один класс с переключателем внутри будет лучше служить?
источник
getClass
иinstanceof
поделиться минусами. Полиморфизм лучше, чем оба, когда он подходит, и я не вижу, чтобы он не соответствовал сценарию использования OP.getClass
я не разделяю ту же проблему, что и при использованииinstanceof
? Мне все еще придется выяснить, что у меня есть, а затем вызвать набор функций. В идеале мне нужен метод, который возвращает данные, специфичные для этого класса, без необходимости приведения к этому объекту.getClass
, это лучший способ сделать это, он не имеет никакого дела с принятием большей части ответа ;-)Обычно, когда мне хочется узнать тип чего-либо, это означает, что я неправильно реализовал структуру своего объекта. В большинстве случаев это сводится к нарушению LSP .
Однако бывают случаи, когда я хотел бы, чтобы у меня был способ выполнить динамическую диспетчеризацию и сэкономить тонну кода котельной плиты и защитить мою структуру будущего. C # предоставляет ключевое слово dynamic в новых версиях фреймворка, но, насколько я знаю, в Java до сих пор нет чего-то подобного.
Тем не менее, instanceof обычно лучше, чем сравнение классов, поскольку он правильно поддерживает наследование. Вы также можете использовать такие методы, как isAssignableFrom и другие из API рефлексии. Если вы хотите реализовать что-то вроде динамической диспетчеризации, это можно сделать с помощью API отражения, но будьте осторожны, это будет медленно. Используйте с осторожностью, в идеале вы должны исправить структуру объекта и дизайн вашего приложения, если можете.
Надеюсь это поможет
источник