Каким образом подтипы отличаются от подклассов в использовании?

Подтип устанавливается, когда класс связан посредством расширения или реализации. Подтипы также используются для дженериков.

Как я могу отличить подтипирование от подклассов?

Ответ 1

В Java создание подклассов является своего рода подтипом.

В Java существует несколько способов создания подтипов:

  1. Когда class A extends B, A является подтипом B потому что B b = new A(...); в порядке
  2. Когда interface A extends B, A является подтипом B потому что B b = new A() {... } в порядке.
  3. Когда class A extends B, A[] является подтипом B[] потому что B[] b = new A[0] в порядке.
  4. Когда 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>().

Ответ 2

В общем случае подклассификация означает наследование атрибутов родителя. Подтипирование просто означает, что операции над супертипом могут выполняться в подтипе. Обратите внимание, что подклассификация является особым случаем подтипирования.

в Java, интерфейсы представляют собой структуру для описания того, какое поведение может проявить тип, что делает его естественным представлением для подтипирования. Подклассификация проявляется в иерархии классов.

Ответ 3

Подкласс не совпадает с подтипом. Вы можете создавать подклассы, которые не являются подтипами. Чтобы понять, что такое подтип, давайте начнем объяснять, что такое тип.

Когда мы говорим, что число 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) явно изменилось, не сохраняя свойства родительского типа. Подумайте, с точки зрения клиента ваших классов. Они могут получить набор целых чисел, где ожидается список целых чисел. Клиент может захотеть добавить значение и получить добавленное значение в список, даже если это значение уже существует в списке. Но она не получит такое поведение, если значение существует. Большой сюрприз для нее!

Это классический пример ненадлежащего использования наследования. Используйте композицию в этом случае.

(фрагмент из: правильно использует наследование).

Ответ 4

На этот раз Википедия дает очень прямой ответ на вопрос:

http://en.wikipedia.org/wiki/Subtype_polymorphism

Подтипирование не следует путать с понятием (класс или объект) наследование от объектно-ориентированных языков; подтипирование является отношением между типами (интерфейсы в объектно-ориентированном языке), тогда как наследование - это отношение между реализациями, вытекающими из язык, позволяющий создавать новые объекты из существующих из них. В ряде объектно-ориентированных языков вызывается подтипирование наследование интерфейса.

Короче говоря, подтипирование происходит, когда вы получаете интерфейс (сигнатуры методов/точки доступа/способы реагирования на внешний мир) от другого, тогда как подклассификация возникает, когда вы получаете реализацию (методы, атрибуты/внутреннее состояние и внутреннюю логику) класс из другого класса через наследование.

Эта терминология часто не используется таким образом, и тип обычно относится к типу .

Ответ 5

В java, subtyping применяется к интерфейсам, но subclasses не применяется к интерфейсам.

Ответ 6

Я не думаю, что Java различает их? У вас есть только классы.