#dart
#dart
Вопрос:
У меня есть класс, который расширяет другой. Родительский класс не предназначен для непосредственного использования API, скорее он реализует базовые методы, которые являются помощниками для дочерних классов.
Когда я использую дочерний класс в программе, я могу видеть все методы из указанного класса, но также и из родительского класса, которые не предназначены для прямого вызова, они существуют для вызова методами дочернего класса.
Я попытался сделать родительский метод закрытым. Я считаю, что это будет работать, если родительский и дочерний элементы объявлены в одной библиотеке. Но у меня проблема с понятием «библиотека». Я понимаю, что часть / часть несколько обесценились, и я хочу, чтобы родительский класс находился в определенном файле. Я не могу понять, как это сделать с помощью импорта / экспорта.
Есть ли способ либо скрыть общедоступный метод из родительского класса от использования всех дочерних классов, либо сделать частный метод из родительского класса вызываемым из всех дочерних классов?
С наилучшими пожеланиями ;
Exemple:
myLib.dart
export mainClass.dart;
MainClass.dar
import baseClass.dart;
class MainClass extends BaseClass {
publicFunc() => ... //Can't call _hiddenFunc, can call wantToHideFunc()
}
Во втором файле (для целей повторного использования кода)
class MainClass extends BaseClass {
_hiddenFunc() => ...
wantToHideFunc() => ...
}
Использование общедоступного API myLib
import myLib.dart
main() {
class = Class();
class.publicFunc(); //Intended
class.wantToHideFunc() //Wants to avoid...
}
Комментарии:
1. Не могли бы вы предоставить образец вашего кода?
2. Может быть, использование композиции было бы более подходящим для вашего использования, чем наследование? Или просто используйте
part
иpart of
. AFAIK, они никуда не денутся.3. Я добавил примеры
Ответ №1:
У Dart нет protected
доступа, подобного Java или C #. Вы не можете скрыть общедоступный элемент, вы не можете получить доступ к закрытому элементу из другой библиотеки, и третьего варианта нет.
Похоже, вам нужны члены суперкласса, которые могут быть вызваны только из подклассов, а не извне объекта. Это то, что вызывается protected
, например, в Java, и у Dart нет ничего подобного. Единственным уровнем конфиденциальности в Dart является library-private, который выбирается, начиная имя с a _
.
Причина, по которой Dart имеет такой дизайн, заключается в том, что изначально это был очень динамичный язык. Вы можете предварительно выполнить «динамические вызовы» для значения со статическим типом dynamic
, скажем dynVal.foo(42)
, и оно вызовет метод с этим именем. Чтобы сделать имя недоступным, оно также должно быть защищено от динамического вызова. Из-за этого Dart privacy не заботится о том, где находится код, выполняющий вызов, его интересует только, знаете ли вы имя, а частные имена библиотек считаются разными именами в зависимости от того, из какой библиотеки они.
Использование part
не рекомендуется в ситуациях, когда оно действительно служит цели. Если вы можете поместить деталь в отдельную библиотеку, это лучше, потому что это позволяет ей иметь собственную конфиденциальность и импорт, но если вам нужны классы для совместного использования конфиденциальности, использование файлов деталей для разделения большого файла вполне разумно. Это инструмент, нет ничего плохого в его использовании, когда это правильный инструмент для работы. Библиотека часто является лучшим инструментом для модульности, но не всегда.
Теперь есть хак, который вы можете использовать:
// Declare the base and provide extensions for "protected" members:
abstract class Base {
int get _someHiddenStuff => 42;
int get somePublicStuff => 37;
}
extension ProtectedBase on Base {
int get someHiddenStuff => _someHiddenStuff;
}
Затем импортируйте это в другую библиотеку и выполните:
import "base.dart";
export "base.dart" hide ProtectedBase;
class SubClass extends Base {
int doSomething => someHiddenStuff somePublicStuff;
}
Тогда любой, кто импортирует «subclass.dart», также получит версию Base
, но не получит ProtectedBase
расширения. Скрытие расширений из общедоступного API вашего пакета позволит вам использовать его, но не позволит пользователям вашего пакета видеть вспомогательные расширения.
(Это, вероятно, сильно переработано, но это вариант. Это эволюция взлома статических / вспомогательных функций верхнего уровня, которые вы не экспортируете.)
Комментарии:
1. Большое вам спасибо за ваше объяснение. И ваш обходной путь! Что касается конфиденциальности библиотеки, я не уверен, что понимаю, если вы скажете, что нет способа сделать это с помощью импорта / экспорта, или если вы скажете, что part / part of является подходящим инструментом для работы, но импорт / экспорт также может работать.
2. Если вы используете конфиденциальность библиотеки для функции, то все классы, взаимодействующие вокруг этой функции, должны находиться в одной библиотеке, что предполагает либо один файл, либо разделение на части. Импорт с этим работать не будет. Если решение не использует конфиденциальность библиотеки для частей, которые вы используете в других классах (подход расширения этого не делает), тогда вы можете использовать импорт. Используйте части, если вам нужно , используйте импорт, если нет.