Классы для начинающих

P.S Этот пост для новичков, опытные разработчики могут его пропустить :)

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

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

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

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

Скажем, все, что вы можете сделать, это создать объекты типа Cat и Parrot, но потом вас поразит, попугай также может говорить как человек, но авторы библиотеки не учли это, так как мне добавить эту функциональность ( говорить как человек) с объектами типа Попугай или любое животное по моему выбору, но не со всеми животными без изменения исходного кода библиотеки?

Здесь могут помочь классы TypeClass, это в основном расширяемость закрытой модели или добавление функциональности в закрытую модель. Итак, как мне добавить свой метод к типу Parrot, если я не могу изменить исходный код.

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

Теперь это черта, которая при смешивании с типом A сделает "A" похожим на человека (или будет иметь человеческие наклонности). ЭКЗЕМПЛЯРОМ ЭТОЙ ЧЕРТЫ - НАШ ТИП-КЛАСС [вы видите, что черта принимает тип] .

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

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

для новичков это краткий способ создания класса, расширяющего HumanTendency, а затем создания объекта этого класса. Это просто более простой способ.

Есть два способа использовать этот класс типов, и я начну с моего наименее любимого. Что в основном определяет функцию, которая принимает попугая в качестве параметра и его класс типа в качестве другого аргумента (предпочтительно неявного), затем он вызывает метод makeHumanLike, уже определенный классом типов, с объектом попугая в качестве параметра.

Вуаля, мы тонко добавили функциональность для ввода parrot с помощью этой функции, теперь, если мы передадим объект parrot в эту функцию с его классом типов в области видимости, мы сможем вызвать makeHumanLike для объекта parrot.

Второй метод, который мне больше всего нравится, включает в себя некоторые имплициты :)

Во-первых, мы определяем неявный класс, который неявно преобразует тип Parrot в произвольный тип (ToParrot), который уже имеет предопределенный метод (назовем его speakLikeHuman), который принимает класс типа в качестве параметра, аналогично предыдущему методу, но какой делает этот метод действительно крутым, так как теперь вместо вызова функции мы можем вызвать parrot.speakLikeHuman, как если бы метод speakLikeHuman уже был частью класса Parrot, а это не так.

Итак, чтобы понять неявный класс, когда мы вызываем parrot.speakLikeHuman, компилятор проверяет, определен ли метод speakLikeHuman для типа parrot. В случае сбоя он затем проверяет, есть ли неявное преобразование из типа parrot в произвольно определенный класс в области видимости, для которой определен метод speakLikeHuman. Это объясняет неявный класс, который принимает тип Parrot и незаметно преобразует его в тип ToParrot, в котором уже определен метод speakLikeHuman.

Сверху оба будут делать то же самое, но со вторым методом кажется более естественным вызывать метод объекта. Но если мы вызовем метод SpeakLikeHuman для Cat, он не будет работать, если в области видимости не указан класс типов Cat.

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

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

Дополнительная информация:



Эта статья следует соглашению и поможет глубже понять, как на самом деле работает большинство типов в Scala.

Https://blog.scalac.io/2017/04/19/typeclasses-in-scala.html