我对这里提到的工厂构造函数示例有些疑问(https://www.dartlang.org/guides/language/language-tour#factory-constructors)。我知道在基本级别上只有三种类型的构造函数-默认,命名和参数化。
我目前正在尝试通过使用泛型来抽象发出不同的 HTTP 请求。我json_serializale用于生成fromJson()和toJson()方法。
这是一个简单的模型文件:
import 'package:json_annotation/json_annotation.dart';
part 'article.g.dart';
@JsonSerializable()
class Article {
int id = 0;
String title = "";
Article({this.id, this.title});
factory Article.fromJson(Map<String, dynamic> json) =>
_$ArticleFromJson(json);
Map<String, dynamic> toJson() => _$ArticleToJson(this);
}
Run Code Online (Sandbox Code Playgroud)
我有一个需要传递fromJson- 方法的通用类,请参阅:
typedef CreateModelFromJson = dynamic Function(Map<String, dynamic> json);
class HttpGet<Model> {
CreateModelFromJson createModelFromJson;
HttpGet({
this.createModelFromJson,
});
Future<Model> do() async {
// [... make HTTP request and do stuff ...]
return createModelFromJson(jsonData);
}
}
Run Code Online (Sandbox Code Playgroud)
最后,这里是ArticleService:
class …Run Code Online (Sandbox Code Playgroud) 所以在dart将new关键字设置为可选之后,
我们可以使用完全相同的语法但不同的内部实现来初始化一个对象。
class Color {
int r = 0, g = 0, b = 0;
Color({this.r, this.b, this.g});
//Named constructors
Color.red() //Implementation
Color.cyan() //Implementation
// Static Initializers
static Color red() => //Initialze with parameter
static Color cyan() => //Initialze with parameter
}
Run Code Online (Sandbox Code Playgroud)
我们可以像这样使用它们,无论它是named constructoror static method:
Color red = Color.red();
Color cyan = Color.cyan();
Run Code Online (Sandbox Code Playgroud)
它们各自的用途是什么?
https://flutter.dev/docs/cookbook/networking/fetch-data
在上一页的最后一个“完整示例”中,
class Album {
final int userId;
final int id;
final String title;
Album({this.userId, this.id, this.title});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
userId: json['userId'],
id: json['id'],
title: json['title'],
);
}
}
Run Code Online (Sandbox Code Playgroud)
它是一个Album类,用于接收请求中收到的JSON字符串并在应用程序中处理它,构造函数除了普通构造函数之外还提供了工厂构造函数。
关于工厂构造函数, https://dart.dev/guides/language/language-tour#constructors
我已阅读上一页的工厂构造函数部分。
示例中Logger类的工厂构造函数并不总是创建新实例,因此我可以理解添加factory关键字,
即使在这个 Complete 示例的 Album 类中,是否也有必要使用工厂构造函数?
对于Album类,由于在工厂构造函数中使用了普通构造函数,因此我觉得这个工厂构造函数(Album.fromJson)总是创建一个新实例。实际上
Future<Album> fetchAlbum() async {
final response =
await http.get('https://jsonplaceholder.typicode.com/albums/16');
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
var temp=json.decode(response.body);
return Album(userId:temp['userId'],id:temp['id'],title:temp['title']);
} else { …Run Code Online (Sandbox Code Playgroud) 我一直在用Dart编写一些代码。我真的很喜欢工厂构造函数,但恐怕我在滥用它的用处。特别是在编写值对象类时,如果验证失败,有时会返回null。
class EmailAddress {
static final RegExp _regex = new RegExp(...);
final String _value;
factory EmailAddress(String input) {
return _regex.hasMatch(input) ? new EmailAddress._internal(input) : null;
}
const EmailAddress._internal(this._value);
toString() => _value;
}
Run Code Online (Sandbox Code Playgroud)
一开始,这似乎还不错。但是,当您实际使用它时,这就是您所看到的。
methodThatCreatesAnEmailAddress() {
var emailAddress = new EmailAddress("definitely not an email address");
...
}
Run Code Online (Sandbox Code Playgroud)
为什么这样不好的论点是,来自另一种静态类型的语言(例如Java或C ++)的开发人员会期望emailAddress始终被初始化为非null值。为什么这是完全可以接受的参数是构造函数是工厂,因此可以返回null值。
那么,这是不好的做法还是利用了有用的功能?
给出以下代码:
const jsonString = '{"myString":"Hello"}';
final jsonMap = jsonDecode(jsonString);
final myObject = MyClass.fromJson(jsonMap);
Run Code Online (Sandbox Code Playgroud)
使用此语法有多少种方法创建新对象:
MyClass.fromJson(jsonMap)
Run Code Online (Sandbox Code Playgroud)
最近,我一直在尝试了解命名构造函数、工厂构造函数和静态方法之间的区别,因此我将我的答案发布在下面,以便我将来可以作为参考。
我在本文中发现了一个有用的解析复杂 JSON 工具。该工具将采用 JSON 示例并用您选择的编程语言对其进行解析。
我目前正在使用 Dart 和我的简单原始 JSON“内容”示例:
{
"title": "Welcome to quicktype!"
}
Run Code Online (Sandbox Code Playgroud)
由Dart 中的 JSON 工具解析后会创建以下 Dart 类:
import 'dart:convert';
Content contentFromJson(String str) => Content.fromJson(json.decode(str));
String contentToJson(Content data) => json.encode(data.toJson());
class Content {
String title;
Content({
this.title,
});
factory Content.fromJson(Map<String, dynamic> json) => new Content(
title: json["title"],
);
Map<String, dynamic> toJson() => {
"title": title,
};
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,工厂构造函数的目的是什么?没有存储 Content 类实例化的“私有”变量。没有检查缓存或键,以便在使用相同原始 JSON 数据参数的后续 Content.fromJson 调用中返回已实例化的 Content 类。
因为使用了factory关键字,这是否意味着Dart仅仅因为该方法被表示为工厂构造函数就在幕后处理重用相同的实例化?
我创建了一个类,我想在命名构造函数或类中可在类外访问的方法中使用异步。当进行命名的建筑工返回一个Future类型,我得到一个错误说:Constructors can't have a return type。
然后我尝试删除Future类型,但我仍然收到一条错误消息,说The modifier 'async' can't be applied to the body of a constructor.
如何在命名构造函数中使用异步?
class HttpService {
Future<void> HttpService.getAll() async {
final response = await http.get(
Uri.encodeFull('http://localhost:4000/'),
headers: {'headers': 'application/json'},
);
if (response.statusCode == 200) {}
}
}
Run Code Online (Sandbox Code Playgroud)
我是 oop 的新手,所以我可能用错了它?接受任何指导。