Scala API 设计; 返回 Set 的服务 其中 I 是某个接口(抽象/特征)
我问了很多关于 Scala 集合类型及其实际使用方式的问题。 考虑一下我如何用 Java 编写一些服务 API/实现:
public interface JavaProductAPI {
public Set<IProduct> getProducts(String isin);
}
现在是 impl:
public class JavaProductAPIImpl implements JavaProductAPI {
private Map<String, Set<ProductImpl>> productsByIsin;
public Set<IProduct> getProducts() {
Set<ProductImpl> s = productsByIsin.get(isin);
return s == null
? Collections.<IProduct>emptySet()
: Collections.<IProduct>unmodifiableSet(s);
}
}
可以说,有一个很好的理由说明为什么我需要在服务实现中访问 ProductImpl
的产品集。 code>,而不是 IProduct
。
似乎在 Scala 中,没有真正的方法可以实现这一点,同时从 API 访问方法显式返回 scala.collection.immutable.Set 。 除非我不介意归还一套副本。
我将假设返回数据的实际副本是不好的做法(请随意争论这一点!):
val productsByIsin: Map[String, scala.collection.Set[ProductImpl]] = ...
def getProducts(isin: String): scala.collection.immutable.Set[IProduct] = {
productsByIsin.get(isin) match {
case Some(s) => scala.collection.immutable.Set(s toSeq :_*)
case None => scala.collection.immutable.Set.empty
}
}
因此,我唯一真正的设计选择是让 API 返回 scala.collection.Set 并使用只读视图:
val productsByIsin: Map[String, scala.collection.mutable.Set[ProductImpl]] = ...
def getProducts(isin: String): scala.collection.Set[IProduct] = {
productsByIsin.get(isin) match {
case Some(s) => s readOnly
case None => scala.collection.Set.empty
}
}
I have asked quite a few questions about the Scala collection types and how they might actually be used. Consider how I might write some service API/implementation in Java:
public interface JavaProductAPI {
public Set<IProduct> getProducts(String isin);
}
And now the impl:
public class JavaProductAPIImpl implements JavaProductAPI {
private Map<String, Set<ProductImpl>> productsByIsin;
public Set<IProduct> getProducts() {
Set<ProductImpl> s = productsByIsin.get(isin);
return s == null
? Collections.<IProduct>emptySet()
: Collections.<IProduct>unmodifiableSet(s);
}
}
Lets say that there's a really good reason why I need to have access within the service implementation to the set of products as being of ProductImpl
s, not IProduct
s.
It seems that in Scala, there's no real way to achieve this whilst at the same time exlicitly returning an scala.collection.immutable.Set
from the API access method. Unless I don't mind returning a copy of the set.
I'm going to assume that returning an actual copy of the data is bad practice (feel free to argue this point!):
val productsByIsin: Map[String, scala.collection.Set[ProductImpl]] = ...
def getProducts(isin: String): scala.collection.immutable.Set[IProduct] = {
productsByIsin.get(isin) match {
case Some(s) => scala.collection.immutable.Set(s toSeq :_*)
case None => scala.collection.immutable.Set.empty
}
}
So that therefore my only real design choice is to have the API return a scala.collection.Set
and use a read-only view:
val productsByIsin: Map[String, scala.collection.mutable.Set[ProductImpl]] = ...
def getProducts(isin: String): scala.collection.Set[IProduct] = {
productsByIsin.get(isin) match {
case Some(s) => s readOnly
case None => scala.collection.Set.empty
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
最后的代码块更接近地模仿您正在模拟的 Java 代码:返回可变集的只读视图。
也就是说,在这种情况下,如果您的支持实现是一个 immutable.Set[ProductImpl] 并且您想要返回一个 immutable.Set[IProduct],那么可以安全地进行强制转换。
Your last block of code more closely mimics the Java code you're emulating: returning a read-only view of a mutable Set.
That said, in this situation, if your backing implementation is an immutable.Set[ProductImpl] and you want to return an immutable.Set[IProduct], it's safe to cast.