Flutter运行时确定类成员类型时Object无法访问子类方法报错
报错原因
Dart是静态类型语言,编译阶段的类型检查只看变量的声明类型,不会追踪运行时的实际赋值类型。
你在Merchant类中把mp成员声明为Object?类型,而Object作为Dart所有类型的顶层父类,本身没有定义printt()方法,所以编译器直接抛出方法不存在的错误,和你运行时动态创建A、B类实例的逻辑没有关系。
你写的泛型工厂方法虽然能正确创建对应实例,但实例赋值给Object?类型的mp后,类型信息被静态类型抹除,编译器无法识别实例自带的printt()方法。
解决方案
方案1:抽象公共接口(推荐,类型安全)
你的A、B两个类都有同名的printt()方法,本质是有公共的行为契约,抽象公共接口是最符合Dart类型设计规范的写法,能同时通过静态检查、保留类型安全:
- 先定义公共抽象接口,约定
printt()方法
abstract class Printable { void printt(); }
- 让A、B类实现这个接口
class A implements Printable { @override void printt() { print('I am function of class A'); } } class B implements Printable { @override void printt() { print('I am function of class B'); } }
- 修改
Merchant类的成员类型和泛型约束
class Merchant { Printable? mp; Merchant(String mpStr) { if (mpStr == 'A') mp = createInstanceOf<A>(); if (mpStr == 'B') mp = createInstanceOf<B>(); } // 给泛型加上边界约束,确保工厂只生成实现了Printable的类型 T? createInstanceOf<T extends Printable>() { final factories = <Type, T Function()>{ A: () => A() as T, B: () => B() as T, }; final createInstance = factories[T]; return createInstance?.call(); } }
修改后直接调用merchant.mp!.printt()即可正常运行,没有编译错误,也不会出现运行时方法找不到的问题。
方案2:类型判断/强转(不推荐,无静态安全保障)
如果不想抽象公共类型,可以在调用方法前手动做类型检查或强转,告诉编译器当前实例的实际类型:
void main() { Merchant merchant = Merchant('A'); // 写法1:类型判断,利用Dart的类型提升自动识别类型,更安全 final mp = merchant.mp; if (mp is A) { mp.printt(); } else if (mp is B) { mp.printt(); } // 写法2:直接强转,类型不对会触发运行时崩溃 // (merchant.mp as A).printt(); }
这种写法把类型校验的责任从编译期转移到了运行时,写错类型就会直接崩溃,非必要不使用。
内容的提问来源于stack exchange,提问作者Özgür Özdemir
相关产品推荐
相关产品推荐

