Подтип устанавливается, когда класс связан посредством расширения или реализации. Подтипы также используются для дженериков.
Как я могу отличить подтипирование от подклассов?
Подтип устанавливается, когда класс связан посредством расширения или реализации. Подтипы также используются для дженериков.
Как я могу отличить подтипирование от подклассов?
В Java создание подклассов является своего рода подтипом.
В Java существует несколько способов создания подтипов:
class A extends B
, A
является подтипом B
потому что B b = new A(...);
в порядкеinterface A extends B
, A
является подтипом B
потому что B b = new A() {... }
в порядке.class A extends B
, A[]
является подтипом B[]
потому что B[] b = new A[0]
в порядке.class A implements B
, A
является подтипом B
потому что B b = new A(...)
в порядке.Похоже, вы хотите, чтобы отличить одного от других. Ниже следует сделать это.
static boolean isSubclass(Class<?> a, Class<?> b) {
return !b.isArray() && !b.isInterface() && b.isAssignableFrom(a);
}
Он не будет обрабатывать подтипы общих классов из-за стирания типов. Экземпляры Class
не переносят параметры типа во время выполнения, поэтому нет способа отличить тип времени выполнения new ArrayList<String>()
от new ArrayList<Integer>()
.
В общем случае подклассификация означает наследование атрибутов родителя. Подтипирование просто означает, что операции над супертипом могут выполняться в подтипе. Обратите внимание, что подклассификация является особым случаем подтипирования.
в Java, интерфейсы представляют собой структуру для описания того, какое поведение может проявить тип, что делает его естественным представлением для подтипирования. Подклассификация проявляется в иерархии классов.
Подкласс не совпадает с подтипом. Вы можете создавать подклассы, которые не являются подтипами. Чтобы понять, что такое подтип, давайте начнем объяснять, что такое тип.
Когда мы говорим, что число 5 имеет тип integer, мы утверждаем, что 5 принадлежит множеству возможных значений (в качестве примера см. возможные значения для примитивных типов Java). Мы также заявляем, что существует допустимый набор методов, которые я могу выполнить для значения, такого как сложение и вычитание. И, наконец, мы заявляем, что существует набор свойств, которые всегда выполняются, например, если я добавлю значения 3 и 5, я получу 8 в результате.
Чтобы привести еще один пример, подумайте об абстрактных типах данных, наборе целых чисел и списке целых чисел, значения, которые они могут удерживать, ограничены целыми числами. Они поддерживают набор методов, таких как add (newValue) и size(). И они оба имеют разные свойства (инвариант класса), Sets не позволяет дублировать, в то время как List разрешает дубликаты (конечно, есть другие свойства, которые оба они удовлетворяют).
Подтип также является типом, который имеет отношение к другому типу, называемому родительским типом (или супертипом). Подтип должен удовлетворять свойствам (значениям, методам и свойствам) родительского типа. Отношение означает, что в любом контексте, где ожидается супертип, его можно подменить подтипом, не затрагивая поведение поведения. Давайте посмотрим на некоторый код, чтобы продемонстрировать, что я говорю. Предположим, что я пишу список целых чисел (в каком-то псевдоязыке):
class List {
data = new Array();
Integer size() {
return data.length;
}
add(Integer anInteger) {
data[data.length] = anInteger;
}
}
Затем я пишу Набор целых чисел как подкласс списка целых чисел:
class Set, inheriting from: List {
add(Integer anInteger) {
if (data.notContains(anInteger)) {
super.add(anInteger);
}
}
}
Наш класс целых чисел является подклассом List of Integer, , но не является подтипом, поскольку он не удовлетворяет всем функциям класса List. Значения и сигнатура методов выполняются, но свойства не являются. Поведение метода add (Integer) явно изменилось, не сохраняя свойства родительского типа. Подумайте, с точки зрения клиента ваших классов. Они могут получить набор целых чисел, где ожидается список целых чисел. Клиент может захотеть добавить значение и получить добавленное значение в список, даже если это значение уже существует в списке. Но она не получит такое поведение, если значение существует. Большой сюрприз для нее!
Это классический пример ненадлежащего использования наследования. Используйте композицию в этом случае.
(фрагмент из: правильно использует наследование).
На этот раз Википедия дает очень прямой ответ на вопрос:
http://en.wikipedia.org/wiki/Subtype_polymorphism
Подтипирование не следует путать с понятием (класс или объект) наследование от объектно-ориентированных языков; подтипирование является отношением между типами (интерфейсы в объектно-ориентированном языке), тогда как наследование - это отношение между реализациями, вытекающими из язык, позволяющий создавать новые объекты из существующих из них. В ряде объектно-ориентированных языков вызывается подтипирование наследование интерфейса.
Короче говоря, подтипирование происходит, когда вы получаете интерфейс (сигнатуры методов/точки доступа/способы реагирования на внешний мир) от другого, тогда как подклассификация возникает, когда вы получаете реализацию (методы, атрибуты/внутреннее состояние и внутреннюю логику) класс из другого класса через наследование.
Эта терминология часто не используется таким образом, и тип обычно относится к типу .
В java, subtyping
применяется к интерфейсам, но subclasses
не применяется к интерфейсам.
Я не думаю, что Java различает их? У вас есть только классы.