dart类初始化 future方案
question:
Let's assume that an initialization of MyComponent in Dart requires sending an HttpRequest to the server. Is it possible to construct an object synchronously and defer a 'real' initialization till the response come back?
In the example below, the _init() function is not called until "done" is printed. Is it possible to fix this?
import 'dart:async';
import 'dart:io';
class MyComponent{
MyComponent() {
_init();
}
Future _init() async {
print("init");
}
}
void main() {
var c = new MyComponent();
sleep(const Duration(seconds: 1));
print("done");
}
Output:
done init
solution1 ,
A constructor can only return an instance of the class it is a constructor of (MyComponent
). Your requirement would require a constructor to return Future<MyComponent>
which is not supported.
You either need to make an explicit initialization method that needs to be called by the user of your class like:
1 2 3 4 5 6 7 8 9 10 11 12 13 | class MyComponent{ MyComponent(); Future init() async { print ( "init" ); } } void main() async { var c = new MyComponent(); await c.init(); print ( "done" ); } |
or you start initialization in the consturctor and allow the user of the component to wait for initialization to be done.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class MyComponent{ Future _doneFuture; MyComponent() { _doneFuture = _init(); } Future _init() async { print ( "init" ); } Future get initializationDone = > _doneFuture } void main() async { var c = new MyComponent(); await c.initializationDone; print ( "done" ); } |
When _doneFuture
was already completed await c.initializationDone
returns immediately otherwise it waits for the future to complete first.
solution2
Probably the best way to handle this is with a factory function, which calls a private constructor.
In Dart, private methods start with an underscore, and "additional" constructors require a name in the form ClassName.constructorName
, since Dart doesn't support function overloading. This means that private constructors require a name, which starts with an underscore (MyComponent._create
in the below example).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import 'dart:async' ; import 'dart:io' ; class MyComponent{ / / / Private constructor MyComponent._create() { print ( "_create() (private constructor)" ); / / Do most of your initialization here, that's what a constructor is for / / ... } / / / Public factory static Future<MyComponent> create() async { print ( "create() (public factory)" ); / / Call the private constructor var component = MyComponent._create(); / / Do initialization that requires async / / await component._complexAsyncInit(); / / Return the fully initialized object return component; } } void main() async { var c = await MyComponent.create(); print ( "done" ); } |
This way, it's impossible to accidentally create an improperly initialized object out of the class. The only available constructor is private, so the only way to create an object is with the factory, which performs proper initialization.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效