Множественное наследование в php — Stack Overflow на русском
Возможно ли наследование свойств и методов от нескольких классов в php?
Если да, то приведите пример, пожалуйста.
- php
- наследование
- множественное-наследование
Возможно ли наследование свойств и методов от нескольких классов в php?
В чистом виде — нет, но начиная с версии 5.4.0, PHP реализует метод для повторного использования кода под названием трейт (trait).
Цитата:
Трейт — это механизм обеспечения повторного использования кода в языках с поддержкой только одиночного наследования, таких как PHP. Трейт предназначен для уменьшения некоторых ограничений одиночного наследования, позволяя разработчику повторно использовать наборы методов свободно, в нескольких независимых классах и реализованных с использованием разных архитектур построения классов. Семантика комбинации трейтов и классов определена таким образом, чтобы снизить уровень сложности, а также избежать типичных проблем, связанных с множественным наследованием и смешиванием (mixins).
Трейт очень похож на класс, но предназначен для группирования функционала хорошо структурированым и последовательным образом. Невозможно создать самостоятельный экземпляр трейта. Это дополнение к обычному наследованию и позволяет сделать горизонтальную композицию поведения, то есть применение членов класса без необходимости наследования.
Пример:
<?php trait ezcReflectionReturnInfo { function getReturnType() { /*1*/ } function getReturnDescription() { /*2*/ } } class ezcReflectionMethod extends ReflectionMethod { use ezcReflectionReturnInfo; /* ... */ } class ezcReflectionFunction extends ReflectionFunction { use ezcReflectionReturnInfo; /* ... */ }
* Подробнее можно почитать в официальной документации по ссылке выше.
Если вам это понадобилось в PHP, значит пора внедрять интерфейсы. Свойства вы так не унаследуете, но опять таки если вам это понадобилось, пора от них избавляться в пользу методов.
Зарегистрируйтесь или войдите
Регистрация через Google
Регистрация через Facebook
Отправить без регистрации
Почта
Необходима, но никому не показывается
Отправить без регистрации
Почта
Необходима, но никому не показывается
Нажимая на кнопку «Отправить ответ», вы соглашаетесь с нашими пользовательским соглашением, политикой конфиденциальности и политикой о куки
c++ — Множественное наследование интерфейса
Изменён 3 года назад
Просмотрен 170 раз
Рассмотрим следующий код:
class IChunk { public; virtual void Method() = 0; }; class FlatChunk : public IChunk { public: void Method() override; }; class IAudioChunk : public IChunk { public: virtual AudioFormat GetFormat() const = 0; }; class IVideoChunk : public IChunk { public: virtual VideoFormat GetFormat() const = 0; }; class SomeAudioChunk : public IAudioChunk, public FlatChunk { public: AudioFormat GetFormat() const override; }; class SomeVideoChunk : public IVideoChunk, public FlatCHunk, { public: VideoFormat GetFormat() const override; };
Это упрощенный код.
Здесь должно происходить следующее:
IChunk
— это интерфейс для работы с каким-то куском данных;FlatChunk
— реализация интерфейсаIChunk
, которая работает с данными, хранящимися в памяти в виде сплошного массива байтов;IAudioChunk
— интерфейс для работы с аудиоданными, который наследуется от интерфейса работы с данными, плюс еще кое-что, специфичное для аудио;IVideoChunk
— интерфейс для работы с видеоданными, который наследуется от интерфейса работы с данными, плюс еще кое-что, специфичное для видео;SomeAudioChunk
— какая-то реализация интерфейсаIAudioChunk
, которая, к тому же, использует реализациюFlatChunk
для работы с данными в виде сплошной последовательности байтов;SomeVideoChunk
— какая-то реализация интерфейсаIVideoChunk
, которая, к тому же, использует реализациюFlatChunk
для работы с данными в виде сплошной последовательности байтов.
В этом коде есть несколько вещей (запахов), которые меня смущают, поэтому при реализации проекта, в котором возникла аналогичная ситуация, я использовал композицию/агрегацию, вместо наследования.
Например, так:
class IAudioChunk { public: virtual IChunk* GetChunk() = 0; virtual AudioFormat GetFormat() const = 0; };
Но я бы хотел обсудить изначальную задумку.
Итак, проблемы первоначального кода заключаются в следующем:
1) SomeAudioChunk
и SomeVideoChunk
наследуют интерфейс IChunk
дважды.
- Во-первых, мне не ясно: можно ли наследоваться от интерфейса и от реализации интерфейса без использования виртуального наследования?
- Во-вторых: потенциальные мысли о необходимости использования в коде виртуального наследования — это запах и повод серьезно задуматься над архитектурой;
- В-третьих: имеет ли значение, в каком порядке происходит наследование от интерфейса и от его реализации?
2) Я не уверен, что между типами IChunk
и IAudioChunk
, а также между типами IChunk
и IVideoChunk
, — существует отношение is a
(является).
has a
в данной ситуации более уместно.Доводы следующие:
- Если
IAudioChunk
иIVideoChunk
наследовать отIChunk
(отношениеis a
), тогда при реализацииSomeAudioChunk
иSomeVideoChunk
нужно как-то и откуда-то брать реализацию интерфейсаIChunk
; брать ее наследованием отFlatChunk
— сомнительный процесс, а писать в ручную — глупо; - Если для
IAudioChunk
иIVideoChunk
использовать композицию/агрегацию, тогда все наследники данных классов не будут зависеть от реализацииFlatChunk
, и даже смогут менять эту реализацию в процессе выполнения, и это очень даже хорошо, гибко, понятно и удобно.
Я хочу найти ответы на свои вопросы. В книгах найти их мне не удалось.
- c++
- наследование
- интерфейс
- агрегация
2
Сначала напишу как я сделал бы:
class IChunk { public: virtual void Method() = 0; }; class FlatChunk : public IChunk { public: void Method() override; }; class IAudioChunk : virtual public FlatChunk { public: virtual AudioFormat GetFormat() const = 0; }; class IVideoChunk : virtual public FlatChunk { public: virtual VideoFormat GetFormat() const = 0; }; class SomeAudioChunk : public IAudioChunk { public: AudioFormat GetFormat() const override; }; class SomeVideoChunk : public IVideoChunk { public: VideoFormat GetFormat() const override; };
Потому что class FlatChunk
уже содержит в себе весь интерфейс IChunk
и определение всех или некоторых функций. Т.е. FlatChunk становится узловым классом для остальной иерархии, и он может быть или не быть абстрактным классом(это вам решать). Но как конкретно подойти к вопросу(использование, агрегация или наследование(открытое или закрытое), обо всем этом нужно еще подумать и пообсуждать)
В вашей реализации, например SomeAudioChunk
, имеет все что есть в IAudioChunk
и FlatChunk
, а значит имеет все виртуальные методы и замещанные методы обеих классов. Т.е. он имеет два чистых виртуальных функции и одну определенную FlatChunk::Method
. Т.е. ваши целевые классы в вашей реализации являются узловыми, а не целевыми. Теперь ответы на ваши вопросы, думаю проясняются, но, если нужно, отвечу конкретно на конкретные вопросы.
Да, наследование происходит дважды(это никчему)
- Да, можно наследовать и интерфейсный класс и класс реализации(но не знаю когда это может понадобится)
Над архитектурой по любому нужно серьезно задуматься.
наследование всего лишь инструмент наследовать от одного и того же обьекта, оно ничего не усложняет.
Нет
- Если наследование открытое, то существует отношение
is a
8
Зарегистрируйтесь или войдите
Регистрация через Google
Регистрация через Facebook
Регистрация через почту
Отправить без регистрации
Почта
Необходима, но никому не показывается
Отправить без регистрации
Почта
Необходима, но никому не показывается
Нажимая на кнопку «Отправить ответ», вы соглашаетесь с нашими пользовательским соглашением, политикой конфиденциальности и политикой о куки
Полное руководство по наследованию ООП в PHP с кодом примера
В этом руководстве мы собираемся узнать о Полном руководстве по наследованию ООП в PHP с кодом примера. Благодаря этому мы узнаем о концепции наследования. Но сначала позвольте мне дать вам краткое объяснение того, что такое объектно-ориентированное программирование (ООП)?
Что такое объектно-ориентированное программирование (ООП)
Объектно-ориентированное программирование состоит из объединения набора переменных (свойств) и функций (методов), которые называются объектом. Эти вещи объединены в классы, в которых отдельные предметы могут быть объединены. ООП может позволить вам рассматривать объекты и многие действия, связанные с объектами в коде программы. Для получения более подробной информации вы можете перейти к моей предыдущей статье Подробнее. [Концепция объектно-ориентированного программирования (ООП) упрощена!]
Что такое наследование?
Наследование — фундаментальная идея объектно-ориентированного программирования. Эту идею можно использовать для определения отношений между двумя классами. В объектной модели PHP поддерживается наследование.
Наследование — это концепция объектно-ориентированного программирования, позволяющая классу использовать свойства и методы другого класса. Мы часто сталкиваемся с ситуациями, в которых мы должны создать новый класс со всеми функциями существующего класса, а также некоторыми дополнительными методами, более похожими на расширение существующего класса. В таких случаях мы можем либо скопировать все свойства и методы существующего класса в новый класс, чтобы сделать их доступными в новом классе, либо мы можем просто наследовать старый класс в новом классе.
Если мы хотим разработать множество похожих классов, можно использовать наследование. Мы можем сгруппировать все общие атрибуты и методы в один родительский класс, который наследуют дочерние классы.
Ключевое слово extends используется для указания унаследованного класса.
Некоторые пояснения к коду: —
, где Человек
— родительский класс (также известный как базовый класс), а Мужской
и Женский
— подкласс или дочерний класс. Публичные и защищенные методы родительского класса передаются дочернему классу. Любой унаследованный метод может быть переопределен или переопределен дочерним классом. Если нет, то при использовании с объектом дочернего класса унаследованные методы сохранят свою функциональность, как описано в родительском классе.
В чем особенность класса при использовании ключевого слова «расширяет»?
- Идея иерархической классификации поддерживается.
- Наследование бывает трех типов: одиночное, множественное и многоуровневое наследование .
- PHP поддерживает только одиночное наследование, когда может быть получен только один класс из одного родительского класса.
- Мы можем имитировать множественное наследование, используя интерфейсов .
Что важно помнить при использовании наследования:
- Дочерний класс может получать доступ и использовать только незакрытые свойства и методы родительского класса.
- Дочерний класс также может иметь собственные методы, которые родительский класс не может найти.
- Кроме того, дочерний класс может переопределить и реализовать метод, указанный в родительском классе.
Пример: Давайте добавим несколько методов в наш класс Human
и посмотрим, как мы можем использовать их в дочерних классах Male
и Female
.
Вывод: —
Некоторое пояснение к примеру: —
Как видно из приведенного выше кода, мы просто унаследовали класс Human в обоих дочерних классах, что позволило им получить доступ и использовать свойства родительского класса. и методы.
Почему мы используем модификатор доступа
protected
в наследовании?Мы узнали о различных модификаторах доступа и о том, как управлять доступом к различным свойствам и методам класса. Если вы не знаете, что такое модификатор доступа, вы можете перейти по данной ссылке. [Полные руководства по модификаторам доступа PHP OOP с примерами кода]
Когда дочерний класс наследует родительский класс, доступ к незакрытым свойствам и методам возможен только для повторного использования. Однако для свойств мы не должны применять модификатор открытого доступа, так как к свойствам также можно получить доступ вне класса.
Мы можем применить модификатор защищенного доступа, чтобы разрешить только дочернему классу доступ к свойствам и методам родительского класса.
Если класс определен как защищенное свойство или метод, свойства и методы могут быть доступны только в дочернем классе, наследующем класс. Давайте разберемся с этим на примере
Пример: —
Вывод: —
Что такое переопределение унаследованных методов в PHP?
Точно так же, как дочерний класс может иметь свои собственные свойства и методы, он может переопределять свойства и методы родительского класса. Когда мы переопределяем свойства и методы класса, мы переписываем метод или свойство, существующее в родительском, снова в дочернем, но присваиваем ему новое значение или код.
Как насчет дочернего класса, использующего процедуру родительского класса, но несколько отличающуюся? Этого можно добиться, переопределив метод, указанный родительским классом, и определив себя. Это называется методом переопределения.
Давайте разберем это на примере: —
Вывод: —
Некоторое пояснение к примеру: —
В приведенном выше коде у нас есть родительский класс с именем Vehicle
и два дочерних класса, а именно Автомобиль
и Мотоцикл
, которые расширяют родительский класс. У нас есть функция drive()
в родительском классе, которую мы переопределили и дали отдельное определение в наших дочерних классах.
Как переопределить родительские свойства и методы в дочернем классе?
Так же, как дочерний класс может иметь свои собственные свойства и методы, он также может переопределять свойства и методы родительского класса. Когда мы переопределяем свойства и методы класса, мы переписываем метод или свойство, которые снова существуют в родительском дочернем объекте, но присваиваем им другой код или значение.
Давайте разберем это на примере: —
Мы создаем hello()
в родительском классе в следующем примере, который возвращает строку «beep» и переопределяет ее в дочернем классе с помощью метода, который производит другую строку, «Привет», используя тот же метод имени.
Вывод: —
Некоторое объяснение примера: —
Результат представляет собой переопределение дочерним методом с тем же именем hello()
родительского класса.
Как предотвратить переопределение методов родительского класса дочерним классом?
Чтобы предотвратить метод, который переопределяет методы родительского класса в дочернем классе, перед этим методом в родительском классе может стоять ключевое слово Final
.
Давайте разберем это на примере: —
Мы определяем функцию hello()
как final
в родительском классе в примере, показанном ниже, но тем не менее попробуем переопределить ее в дочернем классе. Как вы думаете, что может произойти, если мы попытаемся переопределить определенный метод final
?
Вывод: —
Некоторое объяснение примера: —
Поскольку метод hi был определен как родительский класс final
, в дочернем классе мы не можем его переопределить.
Почему важно наследование?
Наследование в объектно-ориентированном программировании — чрезвычайно полезная концепция, позволяющая избежать дублирования кода и упростить решение основных задач.
Все общедоступные и защищенные свойства и методы родительского класса наследуются дочерним классом. Он также может иметь свои особенности и подходы.
Наследование весьма полезно, если мы собираемся создавать множество подобных классов. В один и тот же родительский класс мы можем вставить общие свойства или методы, а затем наследовать их от дочерних классов.
Заключение
Мы используем наследование, чтобы уменьшить дублирование кода за счет использования кода родительского класса в дочерних классах. В этой статье мы узнали о принципе наследования, который является одной из основ объектно-ориентированного программирования. Мы используем наследование, чтобы уменьшить дублирование кода, используя код родительского класса в дочерних классах. Надеюсь, это поможет вам понять концепцию PHP OOP Inheritance. Спасибо
Учебники по основам PHP с базовой демонстрацией от Chentan в 2020 г. – часть 1
Учебники по основам PHP с базовой демонстрацией от Chentan в 2020 г. – Часть 2
- Автор
- Последние сообщения
Ашвани К.
Младший инженер-программист в Cotocus pvt. ltd
Электронная почта — [email protected]
Последние сообщения от Ashwani K (посмотреть все)
Полное руководство по PHP OOP Inheritance с примером кода Как переопределить свойства и методы родителя в дочернем классе Как предотвратить дочерний класс от переопределения родительских методов Наследование имеет важное значение Объектно-ориентированное программирование Объектно-ориентированное программирование (ООП) переопределяет свойства и методы родителя в дочернем классе Переопределение унаследованных методов в PHP PHP ООП-наследование предотвращает дочерний класс от переопределения родительских методов Защищенный Модификатор доступа Модификатор доступа protected в наследовании Руководства по PHP ООП Наследование, которое мы используем Модификатор доступа protected в наследовании Что важно помнить при использовании наследования? в PHP Что такое объектно-ориентированное программирование (ООП) Что такое переопределение унаследованных методов в PHP Почему важно наследование Почему мы используем защищенный модификатор доступа в наследовании
Наследование в объектно-ориентированном PHP | CreativeDev
В этой статье мы изучим наследование PHP. Когда мы говорим о наследовании в PHP, первый и самый основной вопрос, который приходит нам на ум: что такое наследование?
Наследование означает наследование чего-либо из существующего.
Давайте разберемся с концепцией наследования PHP на каком-нибудь примере из реальной жизни, который нас окружает. Все мы знаем, что каждый ребенок получает имущество (например, дом, землю и машину) от своего родителя в качестве наследства.
Джо IS-A сын Джонатана.
В приведенном выше примере отношение между Джонатаном и Джо является родительским и дочерним, что указывает на то, что все имущество, которым обладает Джонатан (родитель), будет автоматически доступно его ребенку Джо (дочернему) в качестве наследства.
Ключевые моменты, которые следует помнить:
- Наследование представляет отношения IS-A между двумя объектами.
- Расширение резервного ключевого слова PHP, используемое для представления наследования в PHP.
Теперь нам приходит в голову вопрос, как мы можем представить эту связь как наследование в PHP? Давайте посмотрим на примере ниже.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/* Родительский класс */ class Jonathan { /* свойство родительского класса */ защищено $ar; защищено $home; охраняемая земля; public function getCar() { return $car; } public function getHome() { return $home; } public function getLand() { return $land; } }
|
В приведенном ниже примере мы видим, что класс Joe (дочерний) является производным от суперкласса Jonathan (родительский) с использованием ключевых слов extends.