Как сделать подкласс

Обновлено: 01.07.2024

Python — объектно-ориентированный язык с начала его существования. Поэтому, создание и использование классов и объектов в Python просто и легко. Эта статья поможет разобраться на примерах в области поддержки объектно-ориентированного программирования Python. Если у вас нет опыта работы с объектно-ориентированным программированием (OOП), ознакомьтесь с вводным курсом или учебным пособием, чтобы понять основные понятия.

Создание классов

Оператор class создает новое определение класса. Имя класса сразу следует за ключевым словом class , после которого ставиться двоеточие:

  • У класса есть строка документации, к которой можно получить доступ через ClassName.__doc__ .
  • class_suite состоит из частей класса, атрибутов данных и функции.

Пример создания класса на Python:

  • Переменная emp_count — переменная класса, значение которой разделяется между экземплярами этого класса. Получить доступ к этой переменной можно через Employee.emp_count из класса или за его пределами.
  • Первый метод __init__() — специальный метод, который называют конструктором класса или методом инициализации. Его вызывает Python при создании нового экземпляра этого класса.
  • Объявляйте другие методы класса, как обычные функции, за исключением того, что первый аргумент для каждого метода self . Python добавляет аргумент self в список для вас; и тогда вам не нужно включать его при вызове этих методов.

Создание экземпляров класса

Чтобы создать экземпляры классов, нужно вызвать класс с использованием его имени и передать аргументы, которые принимает метод __init__ .

Доступ к атрибутам

Получите доступ к атрибутам класса, используя оператор . после объекта класса. Доступ к классу можно получить используя имя переменой класса:

Теперь, систематизируем все.

При выполнении этого кода, мы получаем следующий результат:

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

Вместо использования привычных операторов для доступа к атрибутам вы можете использовать эти функции:

  • getattr(obj, name [, default]) — для доступа к атрибуту объекта.
  • hasattr(obj, name) — проверить, есть ли в obj атрибут name .
  • setattr(obj, name, value) — задать атрибут. Если атрибут не существует, он будет создан.
  • delattr(obj, name) — удалить атрибут.

Встроенные атрибуты класса

Каждый класс Python хранит встроенные атрибуты, и предоставляет к ним доступ через оператор . , как и любой другой атрибут:

  • __dict__ — словарь, содержащий пространство имен класса.
  • __doc__ — строка документации класса. None если, документация отсутствует.
  • __name__ — имя класса.
  • __module__ — имя модуля, в котором определяется класс. Этот атрибут __main__ в интерактивном режиме.
  • __bases__ — могут быть пустые tuple, содержащие базовые классы, в порядке их появления в списке базового класса.

Для вышеуказанного класса давайте попробуем получить доступ ко всем этим атрибутам:

Когда этот код выполняется, он возвращает такой результат:

Удаление объектов (сбор мусора)

Python автоматически удаляет ненужные объекты (встроенные типы или экземпляры классов), чтобы освободить пространство памяти. С помощью процесса ‘Garbage Collection’ Python периодически восстанавливает блоки памяти, которые больше не используются.

Сборщик мусора Python запускается во время выполнения программы и тогда, когда количество ссылок на объект достигает нуля. С изменением количества обращений к нему, меняется количество ссылок.

Когда объект присваивают новой переменной или добавляют в контейнер (список, кортеж, словарь), количество ссылок объекта увеличивается. Количество ссылок на объект уменьшается, когда он удаляется с помощью del , или его ссылка выходит за пределы видимости. Когда количество ссылок достигает нуля, Python автоматически собирает его.

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

Пример работы __del__()
Деструктор __del__() выводит имя класса того экземпляра, который должен быть уничтожен:

Когда вышеуказанный код выполняется и выводит следующее:

В идеале вы должны создавать свои классы в отдельном модуле. Затем импортировать их в основной модуль программы с помощью import SomeClass .

Наследование класса в python

Наследование — это процесс, когда один класс наследует атрибуты и методы другого. Класс, чьи свойства и методы наследуются, называют Родителем или Суперклассом. А класс, свойства которого наследуются — класс-потомок или Подкласс.

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

Класс наследник наследует атрибуты своего родительского класса. Вы можете использовать эти атрибуты так, как будто они определены в классе наследнике. Он может переопределять элементы данных и методы родителя.

Синтаксис наследования класса

Классы наследники объявляются так, как и родительские классы. Только, список наследуемых классов, указан после имени класса.

Возможно ли, кроме того, что я делаю, потому что это не работает, чтобы сделать это? Я хочу иметь подклассы, которые находятся под классом, чтобы использовать CSS специально для этого класса. Класс.

Итак, я могу просто использовать для элементов под родительским классом css "area1", "area2". Я знаю, что могу использовать элемент , чтобы заставить это работать, но я не понимаю, почему он должен быть таким подробным. Не следует ли подкласс css посмотреть, какой родительский класс он находится, чтобы определить его?

Примечание: это работает в IE (с использованием 7 прямо сейчас), но в FF это не так, поэтому я предполагаю, что это не стандартный способ CSS делать что-то.

ОТВЕТЫ

Ответ 1

Просто нужно добавить пробел:

Ответ 2

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

Примените этот стиль к любому элементу, который имеет как класс "area1", так и "item".

К сожалению, это не работает в IE6, но это то, что это значит.

Ответ 3

Ваша проблема, кажется, является недостающим пространством между вашими двумя классами в CSS:

Ответ 4

Ответ 5

Просто поместите пробел между .area1 и .item, например:

этот стиль применяется к элементам с элементом класса внутри элемента с областью класса.

Ответ 6

Просто вставьте пробел между вашими классами

Здесь очень хорошая справка для селекторов CSS.

Ответ 7

После ответа от kR105 ответьте выше:

Моя проблема была похожа на проблему с OP (Original Poster), которая произошла только за пределами таблицы, поэтому подклассы не вызывались из области родительского класса (таблицы), но за его пределами, поэтому я к селекторам ADD, как упомянуто kR105.

В этом была проблема: у меня было две коробки (divs), каждая с одинаковым радиусом границы (HTML5), отступом и разметкой, но для того, чтобы сделать их разными цветами. Вместо того, чтобы повторять эти 3 параметра для каждого класса цветов, я хотел, чтобы "суперкласс" содержал border-radius/padding/margin, а затем отдельные "подклассы", чтобы выразить свои различия (двойные кавычки вокруг каждого, поскольку они не являются действительно подклассами) см. мой более поздний пост). Вот как это получилось:

Надеюсь, что кто-то найдет это полезным.

Ответ 8

Это основа CSS, "каскад" в каскадных таблицах стилей.

Если вы пишете свои правила CSS в одной строке, это упрощает просмотр структуры:

Использование нескольких классов также является хорошим промежуточным/расширенным использованием CSS, к сожалению, есть известная ошибка IE6, которая ограничивает это использование при написании кросс-кода браузера:

IE6 IGNORES первый селектор в правиле многоклассов, поэтому IE6 фактически применяет правило .area1.larger как

Значение будет влиять на ВСЕ. большие элементы.

Это очень неприятная и неудачная ошибка (одна из многих) в IE6, которая заставляет вас почти никогда не использовать эту функцию CSS, если вам нужен один чистый CSS файл с несколькими браузерами.

Тогда решение должно использовать префикс класса CSS, чтобы избежать столкновения с универсальными именами классов:

Можно использовать только один класс, но таким образом вы можете сохранить CSS в логике, которую вы намеревались, зная, что .area1Larger влияет только на .area1 и т.д.

Ответ 9

вы также можете иметь два класса внутри такого элемента

каждый элемент класса является его собственным классом

Ответ 10

Класс, который вы применяете в div, может использоваться, например, как ориентир для элементов стиля с этим div.

Чтобы быть супер-семантичным, вы должны переместить класс в таблицу.

Ответ 11

вы также можете иметь два класса внутри такого элемента

Я не вижу значения этого, поскольку по принципу каскадных стилей последний имеет приоритет. Например, если в моем предыдущем примере я изменил HTML для чтения

рамка рамки и текст будут синими, так как стиль .box2 присваивает эти значения.

Еще одна важная концепция объектно-ориентированного программирования Java - наследование. Что такое наследование, станет понятнее с определенными примерами программирования.

По сути, наследование в Java имеет один родительский класс (называемый super), и второй класс как дочерний элемент родителя (подкласс).

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

В качестве примера наследования мы создадим подкласс, который будет обрабатывать информацию о бонусах за должность. Если работник занимает должность Супервайзера, он получит бонус 100$; если должность Директора филиала, бонус уже составит 200$. Если другая должность - бонус не предоставляется.

Но главное в подклассе - хранить данные бонусов отдельно от данных зарплаты.

Итак, чтоб проверить как работает наследование в Java, создайте новый класс, кликнув File > New File в меню NetBeans. Когда появится диалоговое окно, выберите Java под заголовком Categories и Java Class в разделе File Types. Нажмите Next и введите Bonuses в качестве имени вашего нового класса. Нажмите Finish.

Когда ваш новый класс будет создан, добавьте приватную переменную String и назовите его bonus. Ваш новый класс должен выглядеть следующим образом:

Для создания наследования нужно создать подкласс (дочерний) из класса Java super (родительского), для этого используется ключевое слово extends (в переводе - расширить). Затем после ключевого слова "extends" следует имя родительского класса, который вы хотите расширить. Мы хотим создать подкласс из класса Sales. Класс Sales будет классом super, а класс Bonuses - подклассом.

Вы создали подкласс, который наследует код от класса Sales.

Так же, как и для класса Sales, мы можем создать конструктор для этого нового класса Bonuses. Когда мы создаем объект класса, Java в первую очередь вызывает наш конструктор.

Но! может быть вызван только один конструктор. Если мы вызовем новый конструктор из класса Bonuses, все те значения по умолчанию, которые мы устанавливали для экземпляров класса Sales, не будут установлены. Чтобы обойти это, в Java есть ключевое слово super. Оно делает вызов конструктора из класса super. Добавьте следующий конструктор в свой класс с наследованием Bonuses:

Имя конструктора совпадает с именем класса: Bonuses. Первая строка в фигурных скобках - это вызов super (обратите внимание на круглые скобки после super). Когда выполнится эта строка, все экземпляры по умолчанию, которые мы установили в Sales, будут установлены. Если уберите строку с наследованием (extends имя класса), то ничего не получится!

Вторая строка кода в конструкторе устанавливает значение по умолчанию для переменной String, называемой bonus. (На самом деле вы можете установить более одного конструктора. Как это сделать, вы узнаете в следующем разделе.)

Чтобы проверить свой новый класс, использующий наследование, вернитесь к классу Branch, классу с методом main. Закомментируйте весь код, который у вас есть. Быстрый способ сделать это - выделить весь код, а затем кликнуть по значку Закомментировать на панели инструментов NetBeans:

Чтобы избавиться от комментариев, выделите код еще раз и кликните по значку Раскомментировать.

Теперь добавьте следующую строку, чтобы создать новый объект класса:

Ваше окно кода должно выглядеть примерно так:

Имя объекта просто a1. Тип объекта - это объект Bonuses с наследованием.

Чтобы проверить, что вы можете получить доступ к методам из родительского класса Sales, добавьте эту строку под новым объектом a1:

Это точно так же, как вы делали раньше: вызывали метод salaryWorker класса Sales. Однако на этот раз вы используете объект Bonuses, а не объект Sales.

Добавьте строку для печати, и ваш код должен выглядеть следующим образом:

Запустите программу, чтобы увидеть следующее окно вывода:

Таким образом, метод из родительского класса (класса super) был вызван в действие. Наследование помогло нам обратиться к родительскому классу, что очень удобно!

Теперь мы можем добавить метод в дочерний класс (подкласс).

Добавьте следующий метод в свой класс Bonuses, прямо под конструктором:

Метод называется BonusAward и он настроен на возврат значения String. В круглых скобках метода мы указываем должность работника.

Первая строка метода такова:

Нажмите обратно на класс Branch и добавьте следующую строку, которая использует наш класс с наследованием:

Добавьте в печать переменную award:

Ваш класс Branch должен выглядеть следующим образом (мы удалили все комментарии):

А вот окно вывода при запуске программы:

То есть мы использовали наследование в Java, чтобы отделить данные зарплаты от данных бонуса. Дочерний класс (подкласс) получил доступ к методам своего родителя (super). Затем мы смогли вывести данные из обоих классов.

Наследование Java дает возможность одному классу наследовать свойства другого класса. Также называется расширением класса .

Когда один класс наследуется от другого класса, эти два класса принимают определенные роли. Подкласс расширяет суперкласс. Или подкласс наследует от суперкласса. Подкласс – это специализация суперкласса, а суперкласс – это обобщение одного или нескольких подклассов.

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

Наследование может быть эффективным методом для обмена кодом между классами, которые имеют некоторые общие черты, но позволяя классам иметь некоторые части, которые отличаются.

Вот диаграмма, иллюстрирующая класс с именем Vehicle, который имеет два подкласса, называемые Car и Truck.

объяснение наследования

Класс Vehicle является суперклассом легковых и грузовых автомобилей. Автомобиль и Грузовик – подклассы Автомобиля. Класс Vehicle может содержать те поля и методы, которые нужны всем транспортным средствам (например, номерной знак, владелец и т. д.), Тогда как Car и Truck могут содержать поля и методы, специфичные для легковых и грузовых автомобилей.

Примечание. Некоторые люди утверждают, что наследование – это способ классификации ваших классов в зависимости от того, чем они являются. Автомобиль – это Автомобиль. Грузовик – транспортное средство. Однако на практике это не то, как вы определяете, какие суперклассы и подклассы должны иметь ваше приложение. Обычно это определяется тем, как вам нужно работать с ними в приложении.

Например, вам нужно ссылаться на объекты Car и Truck как объекты Vehicle? Вам нужно обрабатывать объекты Car и Truck одинаково? Тогда имеет смысл иметь общий суперкласс Vehicle для двух классов. Если вы никогда не обрабатываете объекты Car и Truck одним и тем же способом, нет смысла иметь для них общий суперкласс, кроме, возможно, совместного использования кода между ними (чтобы избежать написания дублирующего кода).

Классовые иерархии

Суперклассы и подклассы образуют структуру наследования. На вершине иерархии классов суперклассы. В нижней части иерархии – подклассы. Иерархия может иметь несколько уровней, то есть несколько уровней суперклассов и подклассов. Подкласс сам может быть суперклассом других подклассов и т. д.

Основы

Что унаследовано?

Когда подкласс расширяет суперкласс в Java, он наследует все защищенные и открытые поля и методы, которые становятся его частью, как если бы он объявил их сам. Защищенные и открытые поля можно вызывать и ссылаться так же, как на методы, объявленные непосредственно в нем.

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

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

Единичное наследование

Механизм наследования позволяет наследовать класс только от одного суперкласса (единичное наследование). В некоторых языках программирования, таких как C ++, подкласс может наследоваться от нескольких суперклассов (множественное).

Так как множественный вариант может создать некоторые странные проблемы, например, суперклассы содержат методы с одинаковыми именами и параметрами, он был исключен в Java.

Объявление

Объявляется с использованием ключевого слова extends:

Класс Car в этом примере расширяет класс Vehicle, то есть Car наследуется от Vehicle. Поскольку Car расширяет Vehicle, защищенное поле licensePlate из Vehicle наследуется Car. Когда licensePlate наследуется, оно становится доступным внутри экземпляра Car.

В поле licensePlate на самом деле не ссылаются из класса Car в приведенном выше коде, но можно, если мы захотим:

Ссылка происходит внутри метода getLicensePlate(). Во многих случаях имело бы смысл поместить этот метод в класс Vehicle, где находится поле licensePlate.

Приведение типов

Можно ссылаться на подкласс как на экземпляр одного из его суперклассов. Например, используя определения класса из примера в предыдущем разделе, можно ссылаться на экземпляр класса Car как на экземпляр класса Vehicle. Так как Car расширяет (наследует) Vehicle, он также называется Vehicle.

Вот пример кода Java:

  1. Сначала создается экземпляр автомобиля.
  2. Экземпляр Car присваивается переменной типа Vehicle.
  3. Теперь переменная Vehicle (ссылка) указывает на экземпляр Car. Это возможно, потому что Car наследуется от Vehicle.

Как видите, можно использовать экземпляр некоторого подкласса, как если бы он был экземпляром его суперкласса. Таким образом, вам не нужно точно знать, к какому подклассу относится объект. Например, вы можете рассматривать экземпляры Грузовика и Автомобиля как экземпляры Транспортного средства.

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

Upcasting и Downcasting

Вы всегда можете привести объект подкласса к одному из его суперклассов, либо из типа суперкласса к типу подкласса, но только если объект действительно является экземпляром этого подкласса (или экземпляром подкласса этого подкласса). Таким образом, этот пример downcasting действителен:

Однако следующий приведенный ниже пример недопустим. Компилятор примет его, но во время выполнения, выдаст исключение ClassCastException.

Переопределяющие методы

В подклассе вы можете переопределить методы, определенные в суперклассе:

Обратите внимание, как и класс Vehicle, и класс Car определяют метод setLicensePlate(). Теперь каждый раз, когда setLicensePlate() вызывается для объекта Car, вызывается метод, определенный в классе Car. Метод в суперклассе игнорируется.

Чтобы переопределить метод, сигнатура метода в подклассе должна быть такой же, как в суперклассе, иметь точно такое же имя, количество и тип параметров, последовательность их перечисления. В противном случае метод в подклассе будет считаться отдельным методом.

Невозможно переопределить закрытые методы из суперкласса. Если суперкласс вызывает внутренний метод из другого, он будет продолжать вызывать его из суперкласса, даже при создании частного метода в подклассе с той же сигнатурой.

Аннотация @override

Если вы переопределяете метод в подклассе, и метод внезапно удаляется или переименовывается или его сигнатура изменяется в суперклассе, метод в подклассе больше не переопределяет метод в суперклассе. Было бы хорошо, если бы компилятор мог сказать вам, что переопределяемый метод больше не переопределяет метод в суперклассе, верно?

Для этого и нужна аннотация @ override. Вы размещаете ее над методом, который переопределяет метод в суперклассе:

Вызов методов суперкласса

Если вы переопределяете метод в подклассе, но по-прежнему должны вызывать метод, определенный в суперклассе, используйте ссылку super, например:

В приведенном выше примере кода метод setLicensePlate() в классе Car вызывает метод setLicensePlate() в классе Vehicle.

Вы можете вызывать реализации суперкласса из любого метода в подклассе, как описано выше. Он не должен быть из самого переопределенного метода. Например, вы могли бы также вызвать super.setLicensePlate() из метода в классе Car с именем updateLicensePlate(), который не переопределяет метод setLicensePlate().

Пример инструкции

Java содержит инструкцию с именем instanceof. Она может определить, является ли данный объект экземпляром некоторого класса:

После выполнения этого кода переменная isCar будет содержать значение true.

Инструкция instanceof также может использоваться для определения того, является ли объект экземпляром суперкласса своего класса. Вот пример, который проверяет, является ли объект Car экземпляром Vehicle:

Предполагая, что класс Car расширяет (наследует от) класс Vehicle, переменная isVehicle будет содержать значение true после выполнения этого кода. Объект Car также является объектом Vehicle, поскольку Car является подклассом Vehicle.

Как видите, инструкция instanceof может использоваться для изучения иерархии наследования. Тип переменной, используемый с ней, не влияет на ее результат. Посмотрите на этот пример:

Несмотря на то, что переменная транспортного средства имеет тип Vehicle, объект, на который она в конечном итоге указывает в этом примере, является объектом Car. Поэтому экземпляр транспортного средства автомобиля будет оценен как истинный.

Вот тот же пример, но с использованием объекта Truck вместо объекта Car:

После выполнения этого кода isCar будет содержать значение false. Объект Truck не является объектом Car.

Как наследуются

Как упоминалось ранее, в Java поля не могут быть переопределены в подклассе. Если вы определяете поле в подклассе с тем же именем, что и в суперклассе, поле в подклассе будет скрывать поле в суперклассе. Если подкласс попытается получить доступ к полю, он получит доступ к полю в подклассе.

Однако, если подкласс вызывает метод в суперклассе, который обращается к полю с тем же именем, что и в подклассе, это поле в суперклассе, к которому осуществляется доступ.

Вот пример, который иллюстрирует, как поля в подклассах скрывают поля в суперклассах:

Обратите внимание, как для обоих классов определено поле licensePlate.

И класс Vehicle, и класс Car имеют методы setLicensePlate() и getLicensePlate(). Методы в классе Car вызывают соответствующие методы в классе Vehicle. В результате оба набора методов получают доступ к полю licensePlate в классе Vehicle.

Однако метод updateLicensePlate() в классе Car напрямую обращается к полю licensePlate. Таким образом, он получает доступ к полю licensePlate класса Car. Следовательно, вы не получите тот же результат, если вызовете setLicensePlate(), как при вызове метода updateLicense().

Посмотрите на следующие строки кода:

Этот код распечатает текст 123.

Метод updateLicensePlate() устанавливает значение номерного знака в поле licensePlate в классе Car. Однако метод getLicensePlate() возвращает значение поля licensePlate в классе Vehicle. Следовательно, значение 123, которое устанавливается как значение для поля licensePlate в классе Vehicle с помощью метода setLicensePlate(), является тем, что выводится на печать.

Конструкторы

Механизм наследования не включает конструкторы. Другими словами, конструкторы суперкласса не наследуются подклассами. Подклассы могут по-прежнему вызывать конструкторы в суперклассе, используя конструкцию super().

Фактически, конструктор подкласса должен вызывать один из конструкторов в суперклассе как самое первое действие внутри своего тела. Вот как это выглядит:

Обратите внимание на вызов super() внутри конструктора Car. Этот вызов super() выполняет конструктор в классе Vehicle.

Возможно, вы видели классы, где конструкторы подкласса, похоже, не вызывали конструкторы в суперклассе. Возможно, у суперкласса даже не было конструктора. Тем не менее, конструкторы подкласса все еще называют конструкторы суперкласса в этом случае. Вы просто не могли этого увидеть.

Если класс не имеет какого-либо явного конструктора, компилятор вставляет неявный без аргументов. Таким образом, класс всегда имеет конструктор.

Поэтому следующая версия транспортного средства эквивалентна версии, показанной чуть выше:

Если конструктор явно не вызывает конструктор в суперклассе, компилятор вставляет неявный вызов конструктора no-arg в суперклассе. Это означает, что следующая версия класса Car фактически эквивалентна версии, показанной ранее:

Фактически, поскольку конструктор теперь пуст, мы могли бы опустить его, и компилятор вставил бы его и неявный вызов конструктора no-arg в суперклассе. Вот как тогда будут выглядеть два класса:

Даже если в этих двух классах не объявлено ни одного конструктора, они оба получают конструктор без аргументов, который в классе Car будет вызывать конструктор без аргументов в классе Vehicle.

Если бы класс Vehicle не имел конструктора без аргументов, но имел другой, который принимает параметры, компилятор жаловался бы. Класс Car затем должен был бы объявить конструктор, а внутри него вызвать конструктор в классе Vehicle.

Вложенные классы

Те же правила наследования применяются к вложенным классам. Если объявлены закрытыми, не наследуются. Вложенные классы с модификатором доступа по умолчанию (пакет) доступны только для подклассов, если подкласс находится в том же пакете, что и суперкласс. С модификатором защищенного или открытого доступа всегда наследуются подклассами.

Обратите внимание, как можно создать экземпляр вложенного класса MyNestedClass, который определен в суперклассе(MyClass) посредством ссылки на подкласс(MySubclass).

Финальные классы

Класс может быть объявлен окончательным(final):

Последний класс не может быть продлен. Другими словами, вы не можете наследовать от финального класса.

Абстрактные классы

Класс может быть объявлен абстрактным, который не содержит полную реализацию того, что должен делать. Таким образом, это не может быть реализовано. Другими словами, вы не можете создавать объекты абстрактного класса.

Они предназначены для расширения / создания полной реализации. Таким образом, вполне возможно расширить абстрактный класс. Правила наследования такие же для них, как и для неабстрактных классов.

Читайте также: