Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Интерфейсы (interfaces)

Интерфейсы — это мощный механизм, позволяющий абстрактно описать объект и легко подменять конкретные реализации.

Irnix считает интерфейсом любой объект, имя которого начинается с __ и заканчивается символами __, например __interface_object__. Для таких объектов действует особое правило: директория такого объекта должна содержать только два файла: контракт в файле .self, а также ссылка на конкретную реализацию.

Например, давайте создадим некий __logger__, который имеет метод log, что принимает stdin, форматирует сообщение и всегда выводит его:

~/.local/share/irnix
└── __logger__
    └── .self

Содержимое .self:

log: stdin! stdout!

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

Давайте создадим конкретную реализацию и назовем ее logm:

~/.local/share/irnix
├── __logger__
│   └── .self
└── logm
    ├── .self
	├── log_level -> /bin/logm
    └── log -> /bin/logm

А в .self добавим уже два метода:

log: stdin! stdout!
log_level: stdin! level! stdout!

log принимает stdin, форматирует его и всегда выводит что-то в stdout. А метод log_level работает также как и log, но также принимает один аргумент, а именно уровень.

Важно отметить, что в реализации logm все методы это ссылки на один и тот же бинарный файл logm, который просто форматирует сообщение и выводит его. Более подробно о том, как можно использовать ссылки в Irnix и добиваться высокой гибкости мы рассмотрим в главе "Работа с ссылками".

Теперь просто создадим жесткую ссылку на директорию logm в директории интерфейса:

~/.local/share/irnix
├── __logger__
│   ├── .self
│   └── logm -> ../logm
└── logm
    ├── .self
	├── log_level -> /bin/logm
    └── log -> /bin/logm

После чего метод можно спокойно вызывать как метод на обычном объекте:

echo message | irnix e __logger__.log

Во время запуска Irnix сравнивает оба контракта в __logger__ и в реализации logm для метода log, и если они совпадают, значит реализация подходит. Далее все как обычно, Irnix проверяет вызов и вызывает конкретную реализацию метода log.

Вы также можете не создавать ссылок, а создать реализацию объекта прямо в директории интерфейса:

~/.local/share/irnix
└── __logger__
    ├── .self
	└── logm
	    ├── .self
		├── log_level -> /bin/logm
	    └── log -> /bin/logm

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


Если при этом попытаться вызвать метод __logger__.log_level, то Irnix выведет следующее сообщение:

(Вызываемый метод "log_level" не указан в контракте интерфейса. Однако он указан в контракте объекта: "/home/illia/.local/share/irnix/logm")

The called method "log_level" is not specified in the interface contract. However, it is specified in the objects contract: "/home/illia/.local/share/irnix/logm"

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