Вот и настал момент, когда в спецификацию Dart, после нескольких переработок черновика, добавили фичу Metaobjects, а значит - по ней появилось куда более подробное описание ^_^
Какую проблему решает?
Сейчас мы можем вызывать статический метод или именованный конструктор (например, A.foo()) только через конкретный класс — A. Такое поведение ограничивает нас в работе с дженериками, запрещая в обобщенном коде инстанцировать объекты через их конструкторы или обращаться к их статическим методам (например, Х.foo()).
И это звиздец как бесит 🤬 (по крайней мере меня), т.к. нельзя удобно писать универсальный код, который работает с разными типами, у которых есть похожие статические методы.
Если эта фича пройдет все остальные стадии и будет утверждена, то в Dart появится возможность вызывать статические методы и конструкторы через переменные типа, а не только через точные имена классов:
// Абстрактный интерфейс для печати
abstract class PrettyPrintable<X> {
String prettyPrint(X x);
}
class A static implements PrettyPrintable<A> {
final String name;
A(this.name);
static String prettyPrint(A a) => a.name;
}
class B static implements PrettyPrintable<B> {
final int size;
B(this.size);
static String prettyPrint(B b) => "B of size ${b.size}";
}
// Функция, которая работает с любым типом, поддерживающим PrettyPrintable
String doPrettyprint<X static extends PrettyPrintable<X>>(X x) {
return X.prettyPrint(x);
}
void main() {
print(doPrettyprint(A("MyA")));
print(doPrettyprint(B(42)));
}Из представленного примера видно, как типы A и B используют prettyPrint, но без привязки к конкретному классу на этапе компиляции, что и позволяет писать более универсальный и гибкий код.
Что изменится с релизом фичи?
- Появится позднее связывание статических методов и конструкторов. То есть мы сможем вызывать статические методы или создавать экземпляры классов без жесткой привязки к типу на этапе компиляции. Например, вызов
X.prettyPrint(x)работает так, как если быXбыл классом, а не просто переменной типа. - Добавится возможность объявлять интерфейсы для метаобъектов. Мы сможем объявлять интерфейсы, которые будут реализованы метаобъектами для различных классов, расширяя их возможности и при этом не меняя сам класс. Это увеличит гибкость кода и уменьшит его дублирование.
- Metaobjects дадут доступ к параметрам типа, что позволит писать код, который работает с типами даже в момент их выполнения. Если перефразировать на русский – в коде сына маминой подруги теперь будет дофигище сложных дженериков с заделом на "динамические" структуры данных.
- Изменения в синтаксисе и статическая гарантия типов. Новая пара ключевых конструкций static implements и static extends позволит компилятору гарантировать, что метаобъект будет иметь необходимый интерфейс для вызова соответствующих статических членов или конструкторов.
- Появятся имплицитно генерируемые классы. Для каждого класса, где при его объявлении используются static implements или static extends компилятор автоматически сгенерирует скрытый метаобъект-класс, который переадресует вызовы к статическим методам или конструкторам исходного класса. Передаю пламенный привет виртуальной таблице в C++ 🫠
Уже видите профит от этой Metaobjects?
- 👍 – О, да, детка!!!
- 👌 – Сомнительно, но Окей
- 👎 – Отстой! (Не превращайте Dart в C++)



Дискуссия