Dart密封类特性下,多级密封类能否使用嵌套switch语句?
多级密封类的嵌套Switch实现问题
我定义了多级密封类FailureOrSuccess,其中Success和Failure是它的子类,Failure本身也是密封类,包含AuthFailure子类及多个具体错误类。我想通过外部switch区分Success与Failure,在Failure分支内用嵌套switch区分具体错误类型,但示例代码无法运行,想问这种实现方式是否可行?
我的密封类定义
// 顶层类 sealed class FailureOrSuccess { const FailureOrSuccess(); } // 二级子类 class Success extends FailureOrSuccess { const Success(); } sealed class Failure extends FailureOrSuccess { const Failure(); } // 三级子类 sealed class AuthFailure extends Failure { const AuthFailure(); } // AuthFailure的四级子类 class CancelledByUser extends AuthFailure { const CancelledByUser(); } class ServerError extends AuthFailure { const ServerError(); } class EmailAlreadyInUse extends AuthFailure { const EmailAlreadyInUse(); } class InvalidEmailAndPasswordCombination extends AuthFailure { const InvalidEmailAndPasswordCombination(); } class UnknownError extends AuthFailure { const UnknownError(); }
我的示例代码(无法运行)
switch (state.authFailureOrSuccessOption) { case Success(): { context.router.replace(const DailyRoute()); } case Failure(): { String text; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(switch (???) { case CancelledByUser: return 'Cancelled'; case ServerError: return 'Server Error'; case EmailAlreadyInUse: return 'Email already in use'; case InvalidEmailAndPasswordCombination: return 'Invalid email and password combination'; case UnknownError: return 'An unknown error occurred'; }),)); } }
可行的实现方案
这种嵌套switch的方式完全可行,问题出在你内部switch没有指定要匹配的对象,另外需要确保覆盖Failure的所有子类(密封类特性会强制要求穷尽所有分支)。
修改后的代码如下:
switch (state.authFailureOrSuccessOption) { case Success(): context.router.replace(const DailyRoute()); break; case Failure final failure: // 将当前Failure实例绑定到failure变量 final errorText = switch (failure) { CancelledByUser() => 'Cancelled', ServerError() => 'Server Error', EmailAlreadyInUse() => 'Email already in use', InvalidEmailAndPasswordCombination() => 'Invalid email and password combination', UnknownError() => 'An unknown error occurred', // 后续若给Failure新增非AuthFailure子类,需在此补充对应分支 }; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(errorText)), ); break; }
关键修改点
- 外部
case Failure():中通过final failure绑定当前匹配到的实例,供内部switch使用 - 内部switch直接以这个
failure变量为匹配对象 - 使用Dart模式匹配语法(
CancelledByUser())匹配具体子类,直接返回对应文本简化代码
需要注意:如果后续给Failure添加其他非AuthFailure的子类,必须在内部switch补充对应分支,否则编译器会报错,这也是密封类的优势——确保所有分支都被覆盖。
内容的提问来源于stack exchange,提问作者Charlie Page
相关产品推荐
相关产品推荐

