#dart #mixins
#dart #микшины
Вопрос:
Есть ли способ решить проблему с ромбами при использовании миксинов в Dart? Взгляните на следующий простой пример:
class M1 {
String sayHello() => "hello M1";
}
class M2 {
String sayHello() => "hello M2";
}
class S {
String sayHello() => "hello S";
}
class C extends S with M1, M2 {}
main() {
C c = new C();
print(c.sayHello());
print((c as M1).sayHello());
}
Вывод:
hello M2
hello M2
Если вы вызываете «sayHello» на c, это зависит от порядка миксинов в объявлении класса
C, какая из реализаций выполняется. Всегда используется реализация последнего микшина в списке. Это вряд ли является явным и часто может быть делом случая. Хуже того: реализация суперкласса C всегда скрыта.
Приведение к типу ничего не меняет, что, конечно, согласуется с общей философией Dart, согласно которой тип среды выполнения не играет роли при выполнении кода. Тем не менее, было бы хорошо, если бы были какие-либо средства для явного выбора между различными реализациями. Есть ли такая возможность?
Комментарии:
1. Я не уверен, о чем вы просите. Это также относится к обычному наследованию. Я думаю, что порядок миксинов явный, хотя он такой же, как порядок обычного наследования. Для обычного наследования вы можете использовать,
super
которое еще не доступно для миксинов. Я думаю, что это основная проблема. Команда Dart знает об ограничениях миксинов, и есть планы по их устранению, но, как всегда, они не предоставляют никакой информации, когда это произойдет.2. Ситуация отличается от «обычного» наследования, поскольку множественное наследование в Dart невозможно, не так ли? Проблема, которую я вижу, заключается в том, что я не могу явно выбирать между различными реализациями «sayHello» в том месте, где вызывается функция. Это по-другому решается в C , где можно указать вызов функции именем объявляющего класса (если я правильно помню свои старые дни C ).
3. Нет, это не так. Что я пытался объяснить, так это то, что
(new M2() as M1).sayHello()
при использовании обычного наследования (например,sayHello()
,M1
) этоM2
также вызывало бы неclass M1 extends S {}
реализацию вclass M2 extends M1 {}
, а ту, которая есть в в, а не в в).4. Вы правы в том, что отсутствие super в миксинах ухудшает ситуацию, поскольку вы не можете разрешить конфликт в дочернем классе путем явной пересылки в тот или иной миксин или суперкласс.
5. Хорошо, понял. Приведение также не помогает выбирать между реализацией в родительском и дочернем классах. Таким образом, в этом отношении проблема возникает независимо от миксинов. Но это не делает его лучше 🙂
Ответ №1:
Короче говоря: нет.
Вы не можете решить проблему с ромбовидным шаблоном в Dart, потому что у Dart нет множественного наследования, поэтому у него нет проблемы (или функции).
Добавление миксинов поверх класса — это совершенно обычное одиночное наследование, а реализация класса Dart всегда представляет собой единую цепочку вплоть до объекта. Единственное, что делают миксины, — это позволяют одним и тем же элементам встречаться более чем в одной цепочке.
Это также означает, что нет способа получить доступ к переопределенным элементам выше по цепочке. Вы можете получить доступ только к самому верхнему объявлению или, как функция-член, к самому верхнему объявлению вашей суперцепи (используя super.foo()
).
Комментарии:
1. Я не понимаю вашего «и реализация класса Dart всегда представляет собой единую цепочку вплоть до Object. Единственное, что делают миксины, — это позволяют одним и тем же элементам встречаться более чем в одной цепочке. »