Шаг 91.
Язык программирования Go.
Поддержка встраивания интерфейсов в Go

    На этом шаге рассмотрим встраиваивание интерфейсов в Go.

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

/* Интерфейс ВВерхнийРегистр определяет единственный метод LowerCase(),
не имеющий аргументов и ничего не возвращающий*/
type ВВерхнийРегистр interface{
    ВерхнийРегистр()
}
//Интерфейс ВНижнийРегистр объявлен аналогично
type ВНижнийРегистр interface{
    НижнийРегистр()
}
/*Интерфейс ПреобразоватьРегистр встраивает два интерфейса.
Чтобы конкретный тип удовлетворял требованиям интерфейса ПреобразоватьРегистр,
он должен иметь методы ВерхнийРегистр() и НижнийРегистр()*/
type ПреобразоватьРегистр  interface{
        ВВерхнийРегистр /* Как если бы был объявлен
	                метод ВерхнийРегистр()*/  
	ВНижнийРегистр /* Как если бы был объявлен
	               метод НижнийРегистр()*/
}
}

    Если в первые два интерфейса добавить дополнительные методы (например, ОсобыйВерхнийРегистр() и ОсобыйНижнийРегистр()), интерфейс ПреобразоватьРегистр автоматически включил бы их без изменения его определения.

    Добавим два новых интерфейса:

type СПрописной interface{
	ПерваяПрописная()
}
type  ИзменитьРегистр interface{
	ИзменитьРегистр /* Как если бы были
                           объявлены методы
	                   ВерхнийРегистр() и
	                   НижнийРегистр()*/
	СПрописной        /* Как если бы был объявлен
	                   метод ПерваяПрописная()*/
}

в результате получилась иерархия встроенных интерфейсов как показано на рис. 1


Рис.1. Иерархия встроенных интерфейсов

    Для использования интерфейсов, их нужно реализовать в конкретных типах.

func(part *Part)  ПерваяПрописная() {
	part.Name = НачатьСПрописной(part.Name)
}

    В пользовательский тип Part добавим дополнительный метод ПерваяПрописная(), который воздействует на поле Name, подобно методам LowerCase() и UpperCase(). Все методы, изменяющие регистр символов, требуют передачи приемника по указателю, потому что изменяют само значение, относительно которого вызываются. Методы LowerCase() и UpperCase() реализованы с использованием функций из стандартной библиотеки, а метод ПерваяПрописная() с помощью пользовательской функции НачатьСПрописной().

func НачатьСПрописной(s string) string {
    var chars []rune
    upper := true
    for _, char := range s {
        if upper {
            char = unicode.ToUpper(char)
        }  else  {
            char = unicode.ToLower(char)
        }
        chars = append(chars, char)
        upper = unicode.IsSpace(char) || unicode.Is(unicode.Hyphen, char)
    }
    return string(chars)
}

    Архив с примером можно взять здесь.

    Функция возвращает копию переданной ей строки, где все символы преобразованы в нижний регистр, кроме самого первого и первых символов после пробелов или дефисов, которые преобразуются в верхний регистр.

    На следующем шаге продолжим рассматривать встраивание интерфейсов в Go.


Предыдущий шаг Содержание Следующий шаг