Clojure: О протоколах
Есть еще один вариант, для получения полиморфного поведения, используется он в основном, когда скорость полиморфных функций начинает бить по рукам (так бывает крайне редко), когда хочется избежать expression problem (возможность расширять набор операций над типами данных без изменений определения типов данных), либо необходимо выстроить высокоуровневые абстракции для сложных типов и операций над ними (главное не переусердствовать). Для создания протокола нам потребуется две функции — defprotocol, которая отвечает за генерацию протокола и defrecord, которая создает класс JVM.
Рассмотрим пример:
; Определим протокол, обратите внимание, что
; реализовывать протокол нет необходимости, достаточно определения
(defprotocol Fly
(fly [this] "Method to fly"))
; Теперь создадим класс Bird, в котором определим поведение протокола
(defrecord Bird [name]
Fly
(fly [this] (str (:name this) " flies...")))
; Проверим, наследует ли запись протокол
(extends? Fly Bird)
; => true
; Создадим инстанс класса и свяжем его с идентификатором
(def crow (Bird. "Crow"))
; И вызовем метод, который определили
(fly crow)
; => "Crow flies..."
; Определим еще один класс со своим методом, для закрепления
(defrecord Plane [name]
Fly
(fly [this] (str (:name this) " flew away!")))
(def plane (Plane. "Hawker Hurricane"))
(fly plane)
; => "Hawker Hurricane flew away!"Clojure действительно гибкий язык, в котором можно комбинировать различные подходы, однако некоторые из них (речь про протоколы), вносят усложнения в код, но при правильном применении можно получить абстракции, с которыми удобно работать. В случае с протоколами, выбор в их сторону должен быть обоснован, так как Clojure в целом пропагандирует подход к стремлению делать как можно проще (опять же, сам создатель языка выступал с докладом Simple Made Easy).
Задание
Создайте протокол SaysSomething, затем определите три класса Human, Dog и Cat (такой пример подобран специально :)). В каждом классе определите метод say-something с выводом в консоль (с помощью println) следующей строки:
- Для Human
Hello, World! - Для Cat
Meow, World! - Для Dog
Bark, World!
Поочередно создайте инстанс каждого класса и вызовите у них метод say-something.
Полезное
Clojure: О протоколах
Есть еще один вариант, для получения полиморфного поведения, используется он в основном, когда скорость полиморфных функций начинает бить по рукам (так бывает крайне редко), когда хочется избежать expression problem (возможность расширять набор операций над типами данных без изменений определения типов данных), либо необходимо выстроить высокоуровневые абстракции для сложных типов и операций над ними (главное не переусердствовать). Для создания протокола нам потребуется две функции — defprotocol, которая отвечает за генерацию протокола и defrecord, которая создает класс JVM.
Рассмотрим пример:
; Определим протокол, обратите внимание, что
; реализовывать протокол нет необходимости, достаточно определения
(defprotocol Fly
(fly [this] "Method to fly"))
; Теперь создадим класс Bird, в котором определим поведение протокола
(defrecord Bird [name]
Fly
(fly [this] (str (:name this) " flies...")))
; Проверим, наследует ли запись протокол
(extends? Fly Bird)
; => true
; Создадим инстанс класса и свяжем его с идентификатором
(def crow (Bird. "Crow"))
; И вызовем метод, который определили
(fly crow)
; => "Crow flies..."
; Определим еще один класс со своим методом, для закрепления
(defrecord Plane [name]
Fly
(fly [this] (str (:name this) " flew away!")))
(def plane (Plane. "Hawker Hurricane"))
(fly plane)
; => "Hawker Hurricane flew away!"Clojure действительно гибкий язык, в котором можно комбинировать различные подходы, однако некоторые из них (речь про протоколы), вносят усложнения в код, но при правильном применении можно получить абстракции, с которыми удобно работать. В случае с протоколами, выбор в их сторону должен быть обоснован, так как Clojure в целом пропагандирует подход к стремлению делать как можно проще (опять же, сам создатель языка выступал с докладом Simple Made Easy).
Задание
Создайте протокол SaysSomething, затем определите три класса Human, Dog и Cat (такой пример подобран специально :)). В каждом классе определите метод say-something с выводом в консоль (с помощью println) следующей строки:
- Для Human
Hello, World! - Для Cat
Meow, World! - Для Dog
Bark, World!
Поочередно создайте инстанс каждого класса и вызовите у них метод say-something.
Полезное
Ваше упражнение проверяется по этим тестам
(ns protocols-test
(:require [test-helper :refer [assert-output]]))
(assert-output "Hello, World!\nMeow, World!\nBark, World!")Решение учителя откроется через:
20:00
