Pull to refresh
17
0
Арсений Жижелев @primetalk

Scala архитектор

Send message
P.S. Вышеприведённый вариант — для общего случая, для Int, Double, BigNumber… и других T, для которых есть Numeric[T]. Если delta имеет известный тип, то можно и проще:
  case class SlotDelta[S <: SlotId[Int]](slotId:S, delta: Int) {
    def +:(oldValue:SlotValue[Int, S]) =
      SlotValue(slotId, oldValue.value+ delta)
  }

1. UnionType (by Miles Sabin) используется для того, чтобы сформировать объединённый тип всех свойств, которые уже использовались в текущем объекте

  type SlotsUnion = head.type with tail.SlotsUnion

(Здесь мы используем оператор with, который соответствует конъюнкции. Для проверки принадлежности мы инвертируем условие с помощью оператора <:<

def get[SlotType<:SlotId[_](slotId:SlotType)(implicit ev: SlotSeq1#SlotUnion <:< SlotType) = ???


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

3. Пример с delta. Пусть класс Person содержит 100 полей. И пусть среди этих полей есть свойство типа T: Numeric (например, Int, Double и т.п.). Тогда мы можем объявить специальный класс PropertyDelta, который несёт изменение этого свойства

  case class SlotDelta[T:Numeric, S <: SlotId[T]](slotId:S, delta:T)


Это может быть экономнее, чем копировать оставшиеся 99 полей (при сохранении в БД, при передаче по сети и т.п.). Кроме того, здесь мы явно видим, что именно изменилось, можем проверить допустимость изменения этого свойства согласно каким-либо правилам.

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

  case class SlotDelta[T:Numeric, S <: SlotId[T]](slotId:S, delta: T) {
    def addTo(oldValue:SlotValue[T, S]) =
      SlotValue(slotId, implicitly[Numeric[T]].plus(oldValue.value, delta))
  }


Или немного поинтереснее:

  implicit class SlotValueEx[T:Numeric, S <: SlotId[T]] (slotValue:SlotValue[T, S]) {
    def +(delta:T) =
      SlotValue(slotValue.slotId, implicitly[Numeric[T]].plus(slotValue.value, delta))
  }

Здесь мы сохраняем возможность рефакторинга. Все свойства представлены объектами, хранятся в именованных константах (val'ах). С точки зрения объявления «класса» получается не сильно больше, чем объявление обычного case class'а.
case class Person(
    name: String, 
    address: Address
)

vs.
object Person{
    val name = slot[String]("name")
    val address = slot[Address]("address")
}

Это я немного погорячился. Граф допускает циклы без проблем. Исправил по тексту.

Information

Rating
Does not participate
Location
Воронеж, Воронежская обл., Россия
Registered
Activity

Specialization

Backend Developer, Software Architect
Lead
From 700,000 ₽
Git
Linux
Docker
PostgreSQL
Golang
Scala