参考サイト
Soopyのデータタイプ宣言
http://dev.eyewhale.com/archives/1194
CodeZine
はじめに
Swiftのenum構文が、なんとも(個人的に)気持ちの悪いものになっているので、どうしたら満足できるか考えてみた。
現状
まずは、なぜ気持ちが悪く感じるのかを考えてみた。
Xcode6-Beta7におけるenumの書き方をみてみよう。
protocol ConvertToString {
func toString() -> String
}
enum Weeks : ConvertToString {
case Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
func toString() -> String {
switch self {
case .Sunday: return "日"
case .Monday: return "月"
case .Tuesday: return "火"
case .Wednesday: return "水"
case .Thursday: return "木"
case .Friday: return "金"
case .Saturday: return "土"
}
}
}
みてのとおり、Sunday,Mondayなど、Weeks型に属するものを列挙している。
また、列挙型に属するメソッドは、 caseうんたらとは別の場所に 書かれている。
そして、メソッドのなかで switch文で分岐して処理 されている。
メソッドが「caseうんたらとは別の場所に」書かれ、「switch文で分岐して処理」されるのが、どうやら気持ち悪く感じる原因のようだ。
あくまで個人的意見です。
考察
ざっとWEBを見渡してみた感じでは、enum型のメソッドは、ほとんどswitch文で分岐して処理しているようだ。
それっておかしくないですか?
順に考えていこう。
まず、列挙型の列挙された各値(SundayやMondayなど)は、オブジェクト指向的に考えると、クラスなのだろうか? それとも、オブジェクトなのだろうか?
つまり、型なのだろうか値なのだろうか?
ちょっとコードを見てみよう。
enum Sample {
case OneInteger(Int)
}
let s1 = Sample.OneInteger(1)
let s2 = Sample.OneInteger(2)
このコードをみると、s1とs2は同じSample.OneIntegerでありながら引数が違う。s1とs2が違うオブジェクトであることは明白だろう。
ということは、Sample.OneIntegerはオブジェクトとは言えない。
では、型として考えることは可能だろうか。
これは可能だろう。
上記の例で言えば、Sample.OneInteger(1)は
「1を引数にして、Sample.OneInteger型のオブジェクトを返している」
と考えることが可能だ。
s2も同様。
列挙型の列挙された各値(SundayやMondayなど)を型と考えるならば、enumの中にあるメソッドは型とは別の離れた場所に書かれていることになる。
列挙型でない場合だと以下のように書かれているような感じ。
class Foo {
let val : Int
init(_ val : Int){
self.val = val
}
}
class Bar {
let val : Double
init(_ val : Double){
self.val = val
}
}
let obj1 = Foo(8)
let obj2 = Bar(3.14)
func f(obj : Any){
// switchでうまく書けなかったのでifで書いてある。
// 雰囲気は伝わる(と思いたい…)
if let foo = obj as? Foo {
println("Foo");
}
if let bar = obj as? Bar {
println("Bar")
}
}
f(obj1)
f(obj2)
↑これは気持ち悪い。
メソッドfは、if文やswitch文で分岐処理しないで、型FooやBarのなかにそれぞれの型ごとの処理を書きたい。
そう考えていくと、enumの中のメソッドが、switchで分岐処理してるのもなんか変だと思うことになる。
enumの中でも、switchで分岐しないで型ごとにメソッドを書くほうが、よりオブジェクト指向っぽいのではないだろうか。
あくまで個人的感想だが、自分がどうして気持ち悪いと感じるのかはわかった。
こうあって欲しいという希望
では、どうあって欲しいのか。
メソッドは型の宣言と同時に書きたい。
つまりは、こんな感じ↓
protocol ConvertToString {
func toString() -> String
}
enum NewWeeks : ConvertToString {
case Sunday {
func toString() -> { return "日" }
}
case Monday {
func toString() -> { return "月" }
}
case Tuesday {
func toString() -> { return "火" }
}
case Wednesday {
func toString() -> { return "水" }
}
case Thursday {
func toString() -> { return "木" }
}
case Friday {
func toString() -> { return "金" }
}
case Saturday {
func toString() -> { return "土" }
}
}
ようするに、Soopyのデータタイプみたいな書き方が個人的理想なのだろう…。