是否有关于何时使用案例类(或案例对象)与在Scala中扩展Enumeration的最佳实践指南?
他们似乎提供了一些相同的好处.
假设我有一个类型类,证明Shapeless副产品中的所有类型都是单例类型:
import shapeless._
trait AllSingletons[A, C <: Coproduct] {
def values: List[A]
}
object AllSingletons {
implicit def cnilSingletons[A]: AllSingletons[A, CNil] =
new AllSingletons[A, CNil] {
def values = Nil
}
implicit def coproductSingletons[A, H <: A, T <: Coproduct](implicit
tsc: AllSingletons[A, T],
witness: Witness.Aux[H]
): AllSingletons[A, H :+: T] =
new AllSingletons[A, H :+: T] {
def values = witness.value :: tsc.values
}
}
Run Code Online (Sandbox Code Playgroud)
我们可以证明它适用于简单的ADT:
sealed trait Foo
case object Bar extends Foo
case object Baz extends Foo
Run Code Online (Sandbox Code Playgroud)
然后: …
在Java中你可以:
public enum Enum {
ONE {
public String method() {
return "1";
}
},
TWO {
public String method() {
return "2";
}
},
THREE {
public String method() {
return "3";
}
};
public abstract String method();
}
Run Code Online (Sandbox Code Playgroud)
你是如何在Scala中做到这一点的?
编辑/有用的链接:
正如在SO上多次讨论的那样,如果你没有详尽地列出从密封类派生的所有类型,Scala匹配将警告你.
我想要的是编译时生成的Iterable来自特定父级的案例对象.或者,我很高兴有一种方法可以让编译器告诉我在某些Iterable中没有所有必要的类型.我不想要一个基于反射的运行时方法.
作为第二种方法的一个例子,我想让下面的粗略代码生成一个编译错误.
sealed trait Parent
case object A extends Parent
case object B extends Parent
case object C extends Parent
// I want a compiler error here because C is not included in the Seq()
val m = Seq(A, B).map(somethingUseful)
Run Code Online (Sandbox Code Playgroud)
请告诉我这是不可能的,随意回答.它似乎应该在某种程度上是可能的,因为在确定匹配是非详尽的时,编译器必须完成基本相同的工作.
再考虑一下,除了应用于case对象之外,我会采用类似Enumeration.values()方法的方法.当然,我可以添加一些类似于上面代码的东西,并将一个手动维护的值列表添加到父对象的对象中,但是当编译器可以为我做这件事时,这似乎不必要地容易出错.
// Manually maintained list of values
object Parent {
val values = Seq(A, B, C)
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试为Scala 实现Plurk API,但我有一个设计选择.
例如,Plurk用户的性别属性可以是"男性","女性","其他"之一.
sealed trait Gender
object Male extends Gender
object Female extends Gender
object Others extends Gender
Run Code Online (Sandbox Code Playgroud)
问题是我应该像上面的代码示例那样更喜欢密封的类/对象,而不是Enumeration来表示枚举类型?
因为我发现当我使用其他Scala库时很少遇到Enumeration,并且很多Actor的教程使用密封的类/对象来表示Actor的消息.
那么这是否意味着在Scala中,密封类是比Enumeration更好/更传统的选择?
让我们假设我们有一个密封的特征和一些继承它的案例类:
sealed trait SomeTrait
final case class ClassA(somevalue : Int) extends SomeTrait
final case class ClassB(str : String) extends SomeTrait
(...)
Run Code Online (Sandbox Code Playgroud)
现在我想让所有这些案例类将特征扩展为集合.我将如何继续这样做?我甚至需要在什么类型的类中引用这些类?weakTypeTag?别的什么?
从一般意义上讲,这类似于Travis Brown在这里对case对象做同样的回答.
我的应用程序上下文:我有一个HTTP服务器和一个继承单个密封特征的case类的给定文件(更确切地说:这个层次结构实现了命令设计模式).现在,我想为每个案例类的HTTP-POST自动创建一个端点,并将传入的数据解析upickle到与该端点对应的案例类.以编程方式我不需要其他任何类/类型.
我在SO上读到了一个答案,其中有人说scala枚举是无用的,如果你真的需要,你应该只使用java枚举.
虽然我之前使用过java枚举,但我不能说我完全理解它们,因为我在日常工作中不用java编码.
有人可以解释scala和java枚举之间的区别,以及scala枚举中的缺点究竟在哪里?
我最近偶然发现了Travis Brown @ Iteration在Scala中的一个密封特性上的一段相当棒的代码?.它通过允许枚举ADT"构造函数"(用Haskell的术语)将Scala 基于sealed trait+ case class/object的ADT转换为更接近真实枚举的东西.所以我删除了Travis代码生成的3个弃用警告中的2个,最后是http://pastebin.com/L1gYGJWh,然后我按如下方式使用:
sealed trait KeywordType
case object Crime extends KeywordType
case object Gambling extends KeywordType
case object Porn extends KeywordType
object KeywordType {
/** Maps e.g. "Crime" to Crime */
def withName(x: String): Option[KeywordType] =
adt.enumerate[KeywordType].find(_.toString === x)
}
Run Code Online (Sandbox Code Playgroud)
但是,我很快就需要重用相同的withName逻辑,所以我尝试编写以下ADT基本特征:
trait ADT[T] {
def all: Set[T] = enumerate[T]
def withName(name: String): Option[T] =
all.find(_.toString === name)
}
Run Code Online (Sandbox Code Playgroud)
但是,这不会编译:
Can only enumerate values …Run Code Online (Sandbox Code Playgroud) 我已经读过这个和这个,但我仍然不理解在Scala中这样做的(惯用的)等效方法
enum Status {
OK(1, "Ok", "Okay"),
NOT_OK(5, "Not Ok", "Not Okay")
BAD(10, "Bad", "Run for your life")
int code;
String name;
String description; // custom fields
Status(int code, String name, String description) {
this.code = code;
this.name = name;
this.description = description;
}
}
class Main {
public static void main(String[] args) {
for(Status status : Status.values) { // iterate through them
doStuff(status);
}
}
private doStuff(Status status) {
System.out.println(status.description);
// and more
}
}
Run Code Online (Sandbox Code Playgroud) scala ×9
enumeration ×3
enums ×3
java ×3
case-class ×1
dry ×1
idiomatic ×1
implicits ×1
macros ×1
scala-2.11 ×1
scala-macros ×1
shapeless ×1