На этом шаге мы продолжим рассматривать пример реализации пользовательского типа с единственным значением и приведем реализацию логических операций.
Для всех методов типа NLogic, реализующих логические операции, используется следующий способ - оставить исходное значение нетронутым и вернуть новое значение типа NLogic с результатом логической операции.
Логика работы операции НЕ (NOT) - она возвращает 1.0 для исходного значения 0.0, 0.0 – для исходного значения 1.0, 0.75 – для исходного значения 0.25, 0.25 – для исходного значения 0.75, 0.5 – для исходного значения 0.5 и т. д.
Это первый метод, реализующий логическую операцию, и, подобно другим методам логических операторов, он принимает приемник типа *NLogic.
func (log *NLogic ) Not() *NLogic { return &NLogic{1 - log.val} }
Операция И (AND) возвращает минимальное из указанных значений. Сигнатура метода гарантирует, что его можно будет вызвать как минимум с одним значением (first) типа *NLogic, при этом ему можно передать нуль или более дополнительных значений (rest>). Метод добавляет значение first в конец среза rest и затем выполняет итерации по срезу в поисках минимального значения, меньше значения приемника. Метод возвращает новое значение типа *NLogic, оставляя значение, относительно которого он вызывался, без изменений.
func (log *NLogic ) And() (first *NLogic, rest ...*NLogic) *NLogic { min := log.val rest = append(rest, first) for _, other := range rest { if min > other.val { min = other.val } } return &NLogic{min} }
Операция ИЛИ (OR) возвращает максимальное из указанных значений. Метод Or() структурно идентичен методу And() и отличается только тем, что возвращает максимальное значение.
На следующем шаге рассмотрим реализацию функций сравнения и обратного преобразования типов в этом примере.