如何用 scala 中的不可变 couterpart 替换 java 可变类?
我试图了解如何在 scala 中使用不可变类来替代可变 java 类。
我的示例用例是在数据库中搜索联系人。 当命令式编程时,您将从数据库表中提取每个字段并将其设置在 java 对象上。
在 Scala 中,如何使用不可变类型和函数式风格来做到这一点?
我知道我可以使用构造函数并创建对象的新实例,将所有必需的数据传递给它,但对于大型复杂的数据结构,这似乎并不优雅。
完成此任务的“Scala”/“函数式”方法是什么? 或者与构造复杂的不可变类型相关的一些最佳实践是什么?
public List<Contact> search(String firstName, String lastName) throws SQLException {
List<Contact> contacts = new ArrayList<Contact>();
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = dataSource.getConnection();
ps = con.prepareStatement("select * from contacts where first_name like ? and last_name like ?");
ps.setString(1, "%" + firstName + "%");
ps.setString(1, "%" + lastName + "%");
rs = ps.executeQuery();
while (rs.next()) {
Contact contact = new Contact();
contact.setFirstName(rs.getString("first_name"));
contact.setMiddleName(rs.getString("middle_name"));
contact.setLastName(rs.getString("last_name"));
Date birthday = rs.getDate("birthday");
if (birthday != null) {
contact.setBirthday(new Date(birthday.getTime()));
}
contacts.add(contact);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
rs.close();
ps.close();
con.close();
}
return contacts;
}
联系POJO
import java.util.Date;
public class Contact {
private String firstName;
private String middleName;
private String lastName;
private Date birthday;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
I'm trying to understand how to use immutable classes in scala as a replacement for mutable java classes.
My example use case is searching for contacts in a database.
When programming imperatively you would pull each field from the database table and set it on the java object.
How would you do this in Scala using immutable types and functional style?
I know I could use a constructor and create a new instance of the object passing all required data to it, but for large complex data structures this doesn't seem elegant.
What is the "Scala" / "Functional" way to accomplish this?
Or what are some best practices related to constructing complex immutable types?
public List<Contact> search(String firstName, String lastName) throws SQLException {
List<Contact> contacts = new ArrayList<Contact>();
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = dataSource.getConnection();
ps = con.prepareStatement("select * from contacts where first_name like ? and last_name like ?");
ps.setString(1, "%" + firstName + "%");
ps.setString(1, "%" + lastName + "%");
rs = ps.executeQuery();
while (rs.next()) {
Contact contact = new Contact();
contact.setFirstName(rs.getString("first_name"));
contact.setMiddleName(rs.getString("middle_name"));
contact.setLastName(rs.getString("last_name"));
Date birthday = rs.getDate("birthday");
if (birthday != null) {
contact.setBirthday(new Date(birthday.getTime()));
}
contacts.add(contact);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
rs.close();
ps.close();
con.close();
}
return contacts;
}
Contact POJO
import java.util.Date;
public class Contact {
private String firstName;
private String middleName;
private String lastName;
private Date birthday;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
快速的答案是您使用参数调用构造函数。在 Java 中:
我暂时省略了可选的生日,我们将在 Scala 版本中将其添加回来。
不过,我们仍然有一个可变的联系人列表,所以让我们看看如何使其正确地不可变。我们将使用 Scala 列表。首先,scala 数据对象:
我们有可选的生日作为 type-sig 的一部分作为奖励。
现在让我们定义一个简单的提取器方法,给定一个结果集:
此版本递归地构建结果集中所有联系人的单链接列表。这是不可改变的。
The quick answer is that you call the constructor with your parameters. In Java:
I left out the optional birthday for now, we'll add it back in the Scala version.
We still have a mutable Contacts list though, so lets look at making it properly immutable. We'll use a Scala list. First, the scala data object:
We have optional birthday as part of the type-sig as a bonus.
Now lets define a simple extractor method, given a resultSet:
This version recursively builds up a singly-linked list of all contacts in your ResultSet. This is immutable.
您还可以拥有一个可变构建器,它可以生成您正在寻找的不可变对象。如果临时可变对象保留在其创建范围内并且不会传播到其他地方,那么拥有临时可变对象并没有什么问题。 Scala 标准库实现使用了大量这些库。
这是一个简单的例子(尽管当构造函数很大时这个解决方案更有用):
它可以用作:
You can also have a mutable builder which makes the immutable object you are looking for. There's nothing wrong with having temporary mutable objects if they stay in their creation scope and they are not propagated elsewhere. The Scala standard library implementation use plenty of those.
Here is a simple example (although this solution is more useful when constructors are big):
It can be used as: