LINUX.ORG.RU

Интерфейсы в ООП

 , , , ,


0

2

Введение: Объект != Класс

Тут народ путается с понятиями: интерфейс - переходник, класс - тип, объект - модуль («физическая» часть системы, класс это описание, объект это функционирующая сущность: Состояние+Методы). Многие вообще классы с объектами путают.

Под «физическим» понимается участвующий в работе, а не являющийся описанием. Разница как описанием типа Int, и реальными 32битами в RAM в которых хранится число. Объект это то, что «работает», а «класс» это описание того как данный «тип» должен работать.

Интерфейс: Прослойка между Объектами

Интерфейс - по русски переходник. В программировании используется для отделения и заменяемости модуля от системы. Интерфейс в программировании - набор правил которым должны соответствовать модули разных типов для замены.

  • «Модуль» как правило объект.
  • «Тип» как правило класс.

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

Пример из жизни: электрическая розетка/штепсель - передают энергию на разные устройтсва от разных источников: ГЭС, Генератор, ТЭЦ, Аккумулятор.

В Системной Дизайне Интерфейсы это «прокладки» через которые модули системы становятся отделяемыми и заменяемыми. Это уже не просто «тип-класса», а именно набор правил которым может соответствовать любой тип. Интерфейсы еще называют контрактами - т.е. наборами договоренностей которые должен соблюдать объект.

Заключение: Достаточно Объекта с Интерфейсом

В ЯП есть еще модули, миксины, лябды и прочее словеса которые затрудняют общее понимание системы как набора заменяемых модулей. Класс - это шаблон/тип по которому создаются объекты. Объект это «физический модуль», интерфейс - переходник по которому модули соединятся друг с другом. Вот и всё ООП.

ЭПИЛОГ

В своей статье я расскзаываю, что сделали инженеры Google, а по совместительству создатели UNIX, в языке Go: максимально упростили ООП модель для практического применения.

Убрали классы, убрали наследование, оставили Композицию/Агрегацию и Интерфейсы. Звучит сложно, на деле примитивно: представили программу как набор заменяемых «модулей» подключенных через интерфейсы.

Модульная система, модуль, переходник - термины широко распространненные за границы программирования, и так гораздо понятней на бытовом плане. Интерфейсы окружают нас везде: в быту розетки, в автомобилестроении шины, колесные диски, в компьютерных играх, в лыжном спорте, в сноуборде, в велосипедах. Везде представлена модульная конструкция которая соединяется через «интерфейс» переходников.

Специально я не иду в детальное объяснение принципов проектирования и не пользуюсь словами вроде Dependency Injection. Цель статьи объяснить базовую идею OOD - Объектно Ориентированного Дизайна, того с чем мы сталкиваемся в быту на ежедневной основе: USB порт, крепление смесителя в ванной, приемник карточки в банкомате, диаметр горлышка пластиковой бутылки, габаритные размеры пакета с соком, высота полки в холодильнике, крышка на банке с соленьями, размер куска мыла - всё реализации концепции интерфейса. Каждый из этих объектов соответствует каким-то правилам, сохраняет контакт и делает элементы системы заменяемыми.

UPD #1:

Дорогой @Obezyan, благодаря вашему комментарию, я полностью составил ментальную модель объяснения OOD системы как функционирующего физического агрегата.

  • Объект - это деталь.
  • Класс - чертеж детали.
  • Интерфейс - чертеж соединительного крепления или штекера (интерфейса) по которому идет подключение. Модель крепления, Прокладка, Тип разъема/кабеля для подключения.

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

Более абстрактное представление описывает Robert Martin в своей статье DIP (Dependency Inversion Principle) где интерфейс представляет как абстракцию (абстрактный класс). Что накладывается на преставление штекера для розетки - который питает прибор от абстрактной сети, которая может быть ТЭЦ, ГЭС, Дизель, Аккумулятор, Солнечные Батареи.

UPD #2:

Наследование - это синтаксический сахар над Агрегацией. При Агрегации подключается Компонент явно. При Наследовании Компонент подключается не явно: есть разные механизмы наследования. Базовая идея в перенаправленный СООБЩЕНИЯ на обработку в другой КОМПОНЕНТ. Другим КОМПОНЕТНОМ может быть: базовый класс, объект по прототипу, миксин - базовой идеи делегирования полномочий синтаксическая обертка не меняет.

Факт который не понимает 80% кодеров - наследование это дополнение к ООП, а не его суть. А 99% кодеров не понимает, что ООП это про Сообщения, а не про Компоненты-Объекты. Кодер != Инженер.

Изображение от Sendi Metz: Объект как космическая капсула принимающая и передающая радио сигналы.

Суть от Alan Kay:

I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages (so messaging came at the very beginning – it took a while to see how to do messaging in a programming language efficiently enough to be useful).



Последнее исправление: lbvf50txt (всего исправлений: 4)
Ответ на: комментарий от ugoday

Сходил ТСу в профиль. Там написано:

Программист должен программировать

Странно всё это. =)

wandrien ★★★
()
Ответ на: комментарий от ugoday

@libvf50txt ведёт личный дневничёк на лоре.

До упоминания Столярова осталось 3..2..1…

dataman ★★★★★
()
Ответ на: комментарий от lbvf50txt

В целом, мне кажется, что наследование — скорее неудобная фича. Наследование наследует интерфейс и реализацию (через protected-поля), что ломает инкапсуляцию (сокрытие реализации) и приводит ко всем сопутствующим проблемам (размытые границы, запутанный поток выполнения). Можно, конечно, не использовать protected, но тогда мне сложно представить какие удобства даст наследование. Без доступа к реализации как будто весь смысл наследования теряется.

kaldeon
()
Ответ на: комментарий от ugoday

Множественное наследование в 99% не нужно, а том самом 1% делается через interface + @Delegate за 1 минуту. 99% воплей про «Множественное наследование в java» идёт от людей не программирующих в java и не знающих её.

vtVitus ★★★★★
()
Ответ на: комментарий от vtVitus

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

Ссылка на «множественное наследование» в беседе это неумелая и не очень чистоплотная попытка запугать собеседника «непонятным словом».

lbvf50txt
() автор топика
Ответ на: комментарий от vtVitus

Ну так может быть этот человек писал на C++, где множественное наследование есть.

kaldeon
()
Ответ на: комментарий от ugoday

Вот, я уже дженерики в Го упоминал. Их можно было сделать с самого начала. Но потребовалось 10 лет (а если считать от alef’а, то и все 20), чтобы «теоретически можно» превратилось «готово, можно пользоваться».

Не, до можно пользоваться они так и не доехали.

ya-betmen ★★★★★
()
Ответ на: комментарий от ya-betmen

Лично я знаю только одну фичу го, которая прежде не появилась у какого либо из популярных языков.

Вы вообще поняли, что написали?

  • В Go упростили модель ООП.
  • Ты не понимаешь Go.
  • Конкретнее.
  • Лично я знаю одну фичу Go…
lbvf50txt
() автор топика
Последнее исправление: lbvf50txt (всего исправлений: 1)
Ответ на: комментарий от ugoday

делается за 1 минуту, как я и написал, если уж без геморроя жизни нет.

import lombok.RequiredArgsConstructor;
import lombok.experimental.Delegate;

public class Test {

    public interface IClassA {
        int a1();
        void a2(int y);
        void common();
    }

    public interface IClassB {
        int b1();
        void b2(String y);
        void common();
    }

    @RequiredArgsConstructor
    public class ClassC implements IClassA, IClassB {

        @Delegate
        private final IClassA a;
        @Delegate
        private final IClassB b;

        @Override
        public void common() {
            //for example
            a.common();
            b.common();
        }
    }

    public void test(ClassC c) {
        c.a1();
        c.b2("test");
        c.common();
    }

    public void test() {
        
    }

}
vtVitus ★★★★★
()
Ответ на: комментарий от ya-betmen

Го довольно много перенял, но сделал по-своему, как никто раньше не делал. Например, в каком ещё языке существует неявная реализация интерфейса, проверяемая во время компиляции? Я не знаю такого языка.

kaldeon
()
Ответ на: комментарий от wandrien

Закончат обсуждением лиспа как обычно.

Вносите Лавсана. Только в чистое белое переоденьте.

Obezyan
()
Ответ на: комментарий от lbvf50txt

Много где упростили ооп, начиная с жабоскрипта. Главная фича го не имеет к ооп отношения.

ya-betmen ★★★★★
()
Ответ на: комментарий от vtVitus
  1. Выкинуть из дизайна языка множественное наследование.

  2. Засунуть интерфейсы, чтобы врукопашную оное множественное наследование костылить.

  3. Обвинять окружающих, что у них «без геморроя жизни нет».

ugoday ★★★★★
()

Можно проще:

  1. Интерфейс это требования к изделию (контракт)
  2. Класс это чертёж изделия (реализация)
  3. Объект это готовое изделие (экземпляр)
Obezyan
()
Ответ на: комментарий от imatveev13

Я категорически не приветствую Тикток, но Гуглу стоит взять с них пример и ограничить длину роликов, скажем, 30 или 40 минутами. А то это выходит уже за всякие рамки — что не ролик то полтора часа, Леха Фридман вообще по 6 часов интервью пилить стал.

urxvt ★★★★★
()
Ответ на: комментарий от Obezyan

Хорошая аналогия, мне нравится. Но это взгляд с позиции проектирования. В статье приведет взгляд с позиции функционирующего агрегата: модульная система с горячей заменой модулей, модули крепятся через прокладки, чтоб не прикипели друг к другу.

lbvf50txt
() автор топика
Ответ на: комментарий от urxvt

Вы пишите какой-то ужас и бред. Не нравится - не смотрите длинные ролики, зачем ломать и запрещать, то что кому-то удобно?

1.5 часа это классическая университетская лекция. Вы призываете основной видео-хостинг ограничить возможность выкладывать образовательные лекции, по одой лишь той причине, что вам их «длинно смотреть».

Ну это звиздец.

lbvf50txt
() автор топика
Последнее исправление: lbvf50txt (всего исправлений: 1)
Ответ на: комментарий от lbvf50txt

Ты слишком серьезный. :)

Но да, после 6 часового интервью я в очередной раз убедился, что мир свернул не в ту сторону.

urxvt ★★★★★
()
Ответ на: комментарий от urxvt

Но да, после 6 часового интервью я в очередной раз убедился, что мир свернул не в ту сторону.

Такое длинное интервью - это явное исключение из правил. Оно не может стать систематическим по социально-бытовым законам. Мало кто согласиться держать фокус так долго, три часа это уже на «грани фола» - режиссерская версия для ценителей. У людей «банальный быт», у них нет таких «окон» в рабочий день длинной.

lbvf50txt
() автор топика
Последнее исправление: lbvf50txt (всего исправлений: 1)
Ответ на: комментарий от ugoday

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


func CheckTypeGood(a MyType) { switch a.type...}

funct CheckTypeBad[T MyType](a T) { switch a.type...}
ya-betmen ★★★★★
()
Ответ на: комментарий от lbvf50txt

Просто некоторые люди больше одного предложения написать не в состоянии.

Невозможно не согласиться. Ваше стартовое сообщение в этом треде отличное тому доказательство.

eao197 ★★★★★
()
Ответ на: комментарий от lbvf50txt

У концепции ООП есть создатель, его имя Alan Kay. Есть общепризнанные в мировом сообществе авторы, которые развили концепцию OOD: Sendi Metz, Grady Booch, Robert Martin, Martin Fowler.

В вашем списке имен не хватает Ole-Johan Dahl и Kristen Nygaard (Simula 67), Bertrand Meyer (Eiffel).

Но вообще прикольно получается – первый ОО язык программирования (Simula 67) появиля еще до того, как Алан Кей занялся SmallTalk-ом, но отцом-основателем ООП упорно продолжают называть именно Кея. Маркетинг такой маркетинг.

eao197 ★★★★★
()
Ответ на: комментарий от slackwarrior

О, да, точно. CORBA, IDL. Как ты всё это помнишь? Я вот почти всё позабывал:)

Beewek ★★★
()
Ответ на: комментарий от eao197

первый ОО язык программирования (Simula 67) появиля еще до того, как Алан Кей занялся SmallTalk-ом, но отцом-основателем ООП упорно продолжают называть именно Кея.

Симула – язык программирования и моделирования, а не тотальная ОО-парадигма. Зрелая Симула включает в себя «обычный» алгоритмический АЛГОЛ-60, и не требует общаться с числами с плавающей точкой, как с отдельными объектами со своим поведением.

vM ★★★
()

Это чудовищно.

thesis ★★★★★
()
Ответ на: комментарий от vM

Симула – язык программирования и моделирования, а не тотальная ОО-парадигма.

А я где-то утверждал, что Симула – это парадигма? o_O

Речь шла про то, что первый ООЯ (с наследованием и динамическим полиморфизмом) появился еще до того как Кей хоть что-то сделал в рамках своего SmallTalk-а. Посему приписывать все лавры Кею как-то странно.

и не требует общаться с числами с плавающей точкой, как с отдельными объектами со своим поведением

Т.е. кучу современных языков из категории ООЯ тупо вычеркиваем на основании этого критерия, я все правильно понимаю?

eao197 ★★★★★
()

Да Вас тоже с новым годом ! ПС. Если что уже 14.01.

alnkapa
()
Ответ на: комментарий от eao197

Alan Kay придумал не первый ООЯ, а всю ту ООП-хрень, которая есть в Smalltalkах, вроде посылки объекту false сообщения ifTrue:

В Симуле-67 есть обычный алгоритмический язык, и эта смолточная ООП-хрень не нужна для обычных вычислений.

vM ★★★
()
Ответ на: комментарий от vtVitus

Множественное наследование в 99% не нужно, а том самом 1% делается через interface

ООП в 99% не нужно, а в том самом 1% делается через лямбды и замыкания

(define (make-animal name)
  (let ((name name)
	(weight 0))
    (define (rename new-name)
      (set! name new-name))
    (define (greet)
      (format #t "hello, ~a~%" name))
    (define (weigh) weight)
    (define (feed food-weight)
      (set! weight (+ weight food-weight)))
    (lambda (msg)
      (cond
       ((eq? msg 'rename) rename)
       ((eq? msg 'greet) greet)
       ((eq? msg 'weigh) weigh)
       ((eq? msg 'feed) feed)
       (#t #f)))))

(define (make-owner name)
  (let ((owner-name name))
    (define (owner)
      owner-name)
    (define (own-by new-owner)
      (set! owner-name new-owner))
    (lambda (msg)
      (cond ((eq? msg 'owner) owner)
	    ((eq? msg 'own-by) own-by)
	    (#t #f)))))

(define (make-dog name kind class owner)
  (let ((animal (class name))
	(kind kind)
	(owner (owner "")))
    (define (greet)
      (format #t "hello, good boy, ~a~%" name))
    (define (describe)
      (format #t "This is a ~a named ~a he has ~a kg and his owner ~a can feed him better!~%"
	      kind name ((animal 'weigh)) ((owner 'owner))))
    (lambda (msg)
      (cond
       ((eq? msg 'greet) greet)
       ((eq? msg 'describe) describe)
       (#t (or (animal msg) (owner msg)))))))

;;;; дальше пример работы в repl
scheme@(guile-user)> (define hachiko (make-dog "Hachiko" "Akita" make-animal make-owner))
scheme@(guile-user)> ((hachiko 'own-by) "Ueno")
scheme@(guile-user)> ((hachiko 'feed) 3)
scheme@(guile-user)> ((hachiko 'greet))
hello, good boy, Hachiko
$35 = #t
scheme@(guile-user)> ((hachiko 'describe))
This is a Akita named Hachiko he has 3 kg and his owner Ueno can feed him better!
$36 = #t
scheme@(guile-user)> 

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

ugoday ★★★★★
()
Ответ на: комментарий от vM

Это уже частности конкретной реализации ООП в SmallTalk-е, но т.к. инкапсуляция, наследование и динамический полиморфизм на практике появились раньше, чем Алан Кей хоть что-то явил миру, то приписывать изобретение ООП именно Кею, мягко говоря, странно.

Не менее странно считать ООП именно то, что сделано в SmallTalk. А не в Eiffel, к примеру.

eao197 ★★★★★
()
Последнее исправление: eao197 (всего исправлений: 1)

Терминология не имеет практического смысла, тип или класс, важны только для вашего понимания. Если вы создали класс, как динамический конструктор объектов, то вы его можете назвать типом. А тип из коробки так и будете называть типом, хотя по факту это класс.

dmitry237 ★★★★★
()
Ответ на: комментарий от vM

Вы хотите продемонстрировать свои способности художественной резьбы по цитатам? Ну тогда OK.

Только вот речь же шла не про только лишь динамический полиморфизм.

eao197 ★★★★★
()
Ответ на: комментарий от vM

Когда появились метаклассы?

В классической ООП-шной триаде «инкапсуляция, наследование и полиморфизм» метаклассов нет.

Как их нет и в классических ООП-шных языках вроде Eiffel или Java.

Так что еще раз повторю то, что говорил выше: «Не менее странно считать ООП именно то, что сделано в SmallTalk. А не в Eiffel, к примеру.»

eao197 ★★★★★
()
Ответ на: комментарий от lbvf50txt

Проблема в конечных пользователях которым такая абстракция не нужна - она избыточна.

Типа давайте удалять людям мизинец, т.к большинство не использует. Или уши удалять т.к большинство ими шевелить не умеет.

ya-betmen ★★★★★
()
Последнее исправление: ya-betmen (всего исправлений: 2)
Ответ на: комментарий от ugoday

Я унаследовал от бабушки квартиру. Теперь у меня есть квартира.

Теперь у тебя нет бабушки.

Наследование это круто.

Когда нестановится бабушки, это печально.

Saakx
()
Ответ на: комментарий от Saakx

А вот личные горести в общественное пространство выводить — последнее дело. Мои чувства — моё дело. Это если вам вдруг ещё нужно что такое инкапсуляция объяснять.

ugoday ★★★★★
()
Ответ на: комментарий от dmitry237

А тип из коробки так и будете называть типом, хотя по факту это класс.

Точно.

Класс и Тип это синонимы, точно также как Интерфейс/Протокол/Правила - просто для разных ситуаций используется разное слово. Например в сетях свод правил для взаимодействия между хостами - протокол, а свод правил между уровнями системы - API т.е. интерфейс.

Можно сказать: это горный велосипед профессионального класса.

Можно сказать: это горный велосипед профессионального типа.

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

lbvf50txt
() автор топика
Последнее исправление: lbvf50txt (всего исправлений: 4)
Ответ на: комментарий от Obezyan

Дорогой @Obezyan, благодаря вашему комментарию, я полностью составил ментальную модель объяснения OOD системы как функционирующего физического агрегата.

  • Объект - это деталь.
  • Класс - чертеж детали.
  • Интерфейс - чертеж соединительного крепления или штекера (интерфейса) по которому идет подключение. Модель крепления, Прокладка, Тип разъема/кабеля для подключения.

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

Более абстрактное представление описывает Robert Martin в своей статье DIP (Dependency Inversion Principle) где интерфейс представляет как абстракцию (абстрактный класс). Что накладывается на преставление штекера для розетки - который питает прибор от абстрактной сети, которая может быть ТЭЦ, ГЭС, Дизель, Аккумулятор, Солнечные Батареи.

lbvf50txt
() автор топика
Последнее исправление: lbvf50txt (всего исправлений: 1)
Ответ на: комментарий от vM

Если в Java есть метаклассы, то искомое множественное наследование можно реализовать путём наследования и создания нового метаобъекта. Возьмётесь показать как это работает?

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

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

Это претензия от сппшника? Чудны дела твои господи. Т.е. просто упоротый? Или всё проще и джавист жену увёл? :D :D :D :D

vtVitus ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.