Dart跨文件继承抽象类时私有抽象方法缺失实现未报错问题
问题场景
同文件定义抽象类A和其实现类B的代码如下:
// myclass.dart abstract class A{ _myAbstractMethod(); } class B extends A{ }
同文件场景下编译会抛出错误:MISSING CONCRETE IMPLEMENTATION OF A._myAbstractMethod,属于抽象类实现校验的正常表现。但将类B拆分到独立文件后,编译器不再提示缺失方法实现的错误,该异常表现仅在父类抽象方法为私有方法、两类分属不同文件时出现。
产生原因
和多数面向对象语言的类级私有规则不同,Dart没有类级私有概念,所有以下划线_开头的标识符(方法、属性、类等)都是库级私有,可见边界为当前所属的库,而非所属的类。
- 当A、B在同一个未做特殊关联的.dart文件中时,该文件本身就是一个独立的库,B可以感知到父类A中定义的私有抽象方法
_myAbstractMethod,编译器会正常校验子类是否实现了全部父类抽象方法,缺失实现就会抛出编译错误。 - 当B被拆分到其他独立文件后,两个文件分属两个完全独立的库,B所在的库没有权限访问A所在库的私有成员,对B来说父类A里的
_myAbstractMethod是完全不可见的,编译器不会要求子类实现一个对当前库不可见的方法,因此不会触发编译报错。
注意:该场景下虽然编译阶段不报错,但运行时如果在A所在的库内调用B实例的
_myAbstractMethod,会直接触发NoSuchMethodError,属于隐蔽的运行时风险。
解决方法
- 如果该抽象方法的设计目的就是要求所有子类强制实现,不要将其定义为私有方法:去掉方法名前的下划线,将其声明为公有抽象方法,此时无论子类和父类是否在同一个库,编译器都会正常校验实现逻辑,不会出现漏检。
- 如果确实需要该方法保持库级私有,不要将继承/实现A的子类拆分到其他独立库:要么将子类和父类放在同一文件,要么使用
part指令将子类所在文件纳入父类所属的库,保证私有方法对子类可见,编译器的实现校验就会正常生效。 - 如果必须拆分到不同库,又要强制子类实现对应逻辑,可以在父类中定义公有的模板方法,将私有方法的调用逻辑封装在公有方法中,同时在父类中对未实现的逻辑做显式的异常抛出,避免无提示的运行时崩溃。
内容的提问来源于stack exchange,提问作者aguiadouro
相关产品推荐
相关产品推荐

