Как сделать структурную типизацию

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

Простейший пример: если есть некий тип данных POINT { float x, y; }, и есть некий тип MyPoint { float x, y; } то благодаря структурной типизации тип MyPoint можно применять там же, где и POINT (и наоборот). Более того, если объявлен некоторый тип MySuperPoint { int i, j; float z; char str[10]; float z, k, y; } то его тоже можно применять вместо POINT и MyPoint. Для структурной типизации достаточно совпадения имен внутренних имен и совместимости типов.



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

Структурный интерфейс - это специальный тип данных, идеологически подобный обычному интерфейсу. Структурный интерфейс определяет имена и типы данных.
Поскольку реальные структуры, на которые может указывать структурный интерфейс, могут быть самые различные, то единственным способом внутреннего представления структурного интерфейса может быть таблица ссылок на переменные и функции. Именно так реализованы интерфейсы в языке Go.

interface IPoint
{
  int x, y;
  int Square();
};

этот интерфейс содержит две ССЫЛКИ на переменные типа int (фактически два указателя) и одну ССЫЛКУ на функцию (фактически один делегат).

Если у нас есть некоторый тип
struct MyPoint
{
  int x, y, z;
  int Square() { return x * y; }
  int Volume() { return x * y * z; }
}

то переменные этого типа можно свободно передавать туда, где в качестве аргумента требуется структурный интерфейс.
func Foo(IPoint p)
{
  printf("Square =  %d", p.Square() );
}

MyPoint mp;
Foo(mp);

Если в передаваемом типе есть какое-то несоответствие (например, нет переменной с именем x или метода Square), то будет ошибка компиляции. Это вполне нормально.

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




No comments:

Post a Comment