首页 > 解决方案 > Dart - Hide method from parent class / call private method from parent class

问题描述

I have a class that extends another. The parent class is not intended to be used directly by the API rather it implements basic methods that are helpers for child classes.

When I use the child class in a program I can see all method from said class but also the one from the parent class that are not intended to be called directly, they exist to be called by the methods of the child class.

I tried to make parents method private. This would work I believe as long as parent and child are declared in the same library. But I have an issue with the "library" notion. I understand part/part of are somewhat depreciated, and I want the parent class to be in a specific file. I can't figure a way to do it with import/export.

Is there a way to either hide a public method from the parent class from all child classes usage or to make a private method from the parent class callable from all child classes ?

Best regards ;

Exemple:

myLib.dart

export mainClass.dart;

mainClass.dar

import baseClass.dart;

class MainClass extends BaseClass {
    publicFunc() => ... //Can't call _hiddenFunc, can call wantToHideFunc()

}

In a second file (for code reusability purposes)

class MainClass extends BaseClass {
    _hiddenFunc() => ...
    wantToHideFunc() => ...
}

Using myLib public API

import myLib.dart
main() {
    class = Class();
    class.publicFunc(); //Intended
    class.wantToHideFunc() //Wants to avoid...
}

标签: dart

解决方案


Dart 没有protectedJava 或 C# 那样的访问权限。您不能隐藏公共成员,不能从其他库访问私人成员,也没有第三种选择。

听起来你想要只能从子类调用的超类成员,而不是从对象外部调用。这就是protected在例如 Java 中所调用的,而 Dart 没有类似的东西。Dart 中唯一的隐私级别是 library-private,通过名称以_.

Dart 之所以有这样的设计,是因为它原本是一种非常动态的语言。您可以对具有静态类型的值执行“动态调用” dynamic,例如dynVal.foo(42),它将调用该名称的方法。为了使名称无法访问,它还需要避免动态调用。因此,Dart 隐私不关心执行调用的代码在哪里,它只关心你是否知道名称 - 库私有名称被视为不同的名称,具体取决于它们来自哪个库。

part在实际服务于目的的情况下,不鼓励使用。如果您可以将零件放入自己的库中,那就更好了,因为它允许它拥有自己的隐私和导入,但如果您需要类共享隐私,使用零件文件分割一个大文件是完全合理的。它是一种工具,当它是适合工作的工具时,使用它没有任何问题。库通常是更好的模块化工具,但并非总是如此。

现在,您可以使用一个hack :

// 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 中隐藏扩展将允许您使用它,但会阻止您的包的用户看到帮助程序扩展。

(这可能是高度过度设计的,但它是一种选择。它是具有您不导出的静态/顶级辅助函数的黑客的演变。)


推荐阅读