Scala API 设计; 返回 Set 的服务 其中 I 是某个接口(抽象/特征)

发布于 2024-07-15 04:10:08 字数 1596 浏览 9 评论 0原文

我问了很多关于 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 ProductImpls, not IProducts.

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

折戟 2024-07-22 04:10:08

最后的代码块更接近地模仿您正在模拟的 Java 代码:返回可变集的只读视图。

也就是说,在这种情况下,如果您的支持实现是一个 immutable.Set[ProductImpl] 并且您想要返回一个 immutable.Set[IProduct],那么可以安全地进行强制转换。

import scala.collection._

trait IProduct
class ProductImpl extends IProduct

val productsByIsin: immutable.Map[String, immutable.Set[ProductImpl]] =
  immutable.Map.empty
def getProducts(isin: String): immutable.Set[IProduct] =
  productsByIsin.getOrElse(isin, immutable.Set.empty).asInstanceOf[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.

import scala.collection._

trait IProduct
class ProductImpl extends IProduct

val productsByIsin: immutable.Map[String, immutable.Set[ProductImpl]] =
  immutable.Map.empty
def getProducts(isin: String): immutable.Set[IProduct] =
  productsByIsin.getOrElse(isin, immutable.Set.empty).asInstanceOf[immutable.Set[IProduct]]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文