Created
June 21, 2011 13:44
-
-
Save j5ik2o/1037873 to your computer and use it in GitHub Desktop.
列挙型っぽいもの
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import collection.mutable.ListBuffer | |
/**列挙型定数を表すトレイト。 | |
* | |
* @author j5ik2o | |
*/ | |
trait EnumEntry extends Serializable with Ordered[EnumEntry] { | |
/**列挙定数の序数 (列挙宣言での位置)。 */ | |
private[util] var ordinalNo: Int = _ | |
def ordinal = ordinalNo | |
private def simpleName = getClass.getSimpleName match { | |
case x if x.endsWith("$") => x.init | |
case x => x | |
} | |
/**宣言されているとおりの 列挙型定数の名前。*/ | |
val name = simpleName.substring(simpleName.lastIndexOf('$') + 1) | |
override def toString = "%s:%d".format(name, ordinal) | |
def compare(that: EnumEntry) = this.ordinal compare that.ordinal | |
} | |
/**列挙型定数を定義するための要素。 | |
* | |
* @author j5ik2o | |
*/ | |
class DeclareEntry[T <: EnumEntry](enum: AbstractEnum[T]) { | |
def %(value: T) = andThen(value) | |
def andThen(value: T) = { | |
enum.appendValue(value) | |
this | |
} | |
} | |
/**列挙型のための骨格実装。 | |
* | |
* @author j5ik2o | |
*/ | |
abstract class AbstractEnum[T <: EnumEntry] extends Serializable { | |
private var counter: Int = _ | |
private val enums = ListBuffer.empty[T] | |
implicit def enumEntryToDeclareEntry(entry: T) = declared(entry) | |
private[util] def appendValue(value: T) = { | |
counter += 1 | |
value.ordinalNo = counter | |
enums += value | |
} | |
def declared(value: T): DeclareEntry[T] = { | |
appendValue(value) | |
new DeclareEntry(this) | |
} | |
/**序数から列挙型定数を取得するためのファクトリメソッド。 | |
* | |
* @param ordinal 序数 | |
*/ | |
def apply(ordinal: Int) = | |
enums.find(_.ordinal == ordinal).get | |
/**名前から列挙型定数を取得するためのファクトリメソッド。 | |
* | |
* @param name 名前 | |
*/ | |
def apply(name: String) = | |
enums.find(_.name == name).get | |
/**すべての列挙型定数を取得する。 | |
* | |
* @return 列挙型定数のリスト | |
*/ | |
def values: List[T] = enums.result | |
} | |
// --- 以下、使い方 | |
sealed trait Language extends EnumEntry | |
object Language extends AbstractEnum[Language] { | |
case object Japanese extends Language | |
case object English extends Language | |
case object Chinese extends Language | |
// 定数を登録(この並びで序数が決まります)。 | |
Japanese % English % Chinese | |
} | |
class EnumTest extends AssertionsForJUnit { | |
@Test | |
def test { | |
println(Language.values) | |
println(Language.Japanese) | |
println(Language.Japanese.ordinal) | |
println(Language.Japanese.name) | |
println(Language(1)) | |
println(Language("Japanese")) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment