我不明白为什么下面的例子不起作用:

void main() {
  final BaseClass something = ConcreteClass('test');

  if (something is I) {
    print(something.exists); // The getter 'exists' isn't defined for the type 'BaseClass'.
  }
}

abstract interface class I {
  String get exists;
}

abstract class BaseClass {}

class ConcreteClass extends BaseClass implements I {
  ConcreteClass(this.exists);

  @override
  final String exists;
}

我是否达到了这里提到的类型提升中的"getter"限制:https://dart.dev/tools/non-promotion-reasons#not-field

如果是这样的话,我如何在不诉诸施法的情况下解决这个问题(我尽量避免)? 把exists加到BaseClass不是我真正的代码中的选项.

此外,Dart 3.3的发行说明说:

抽象getters现在可以根据私有final规则提升 如果没有冲突的声明,现场推广.

...听起来像是我想要的

推荐答案

The problem you are hitting are described here:
https://dart.dev/tools/non-promotion-reasons#subtype-mismatch

简而言之,问题是您试图进行类型提升,这将从something变量中删除功能.在这种情况下,如果您将类型提升为Isomething变量的类型将变为I,但它不再是BaseClass.因此,由于Dart没有在同一个变量上多个类型的概念,它不能说something既是BaseClass又是I.

一个解决方案是做一个类型转换:

void main() {
  final BaseClass something = ConcreteClass('test');

  if (something is I) {
    print((something as I).exists);
  }
}

但是,既然你想避免这种情况,你也可以声明一个新变量.如果我们使用一个模式,这实际上是相当简单的:

void main() {
  final BaseClass something = ConcreteClass('test');

  if (something case I something) {
    print(something.exists);
  }
}

这里,如果方法变量somethingI,我们为if—block声明一个新的局部变量,称为something.由于本地something属于类型I,所以它不允许从BaseClass类调用任何方法.

如果你需要同时使用IBaseClass的功能,我建议在模式中使用不同的变量名称.

更多详细信息和解决方案,请阅读我在开头提到的链接.

Dart相关问答推荐

Dart:判断泛型函数的类型 T

对字母数字字符串数组进行排序

为什么使用三元条件运算符会产生return_of_invalid_type错误?

Dart/Flutter ffi(外部函数接口)本机回调,例如:sqlite3_exec

如何在streambuilder中查询firestore文档并更新listview

设置文本以匹配Flutter中的列宽

AnimatedContainer 可以为其高度设置动画吗?

如何等待forEach完成异步回调?

为http POST请求从Flutter上的TextFormField捕获数据

为什么 Dart 内置的 List 接口可以实例化?

有没有办法知道我的Flatter应用程序使用的是哪个Android API版本?

在 Dart 中向服务器发出多个独立请求的最佳方式

将ListTile图标向左对齐

Firebase 手机身份验证Flutter crash崩溃

断言失败时如何在 Dart 中打印消息?

Dart - 如何在每次测试之后或之前运行函数?

Dart 会在多核环境中并行执行隔离吗?

如何在抽象类中声明工厂构造函数?

何时在 Dart 中使用 part/part of 与 import/export?

const 构造函数实际上是如何工作的?