Menu
Coddy logo textTech

ポリモーフィズム

CoddyのSwiftジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 32/57。

ポリモーフィズムとは、1つのコードがさまざまな型の値で動作し、それぞれの値が独自の方法で応答することを意味します。以下のループは、どの動物を保持しているかを知らずにsound()を呼び出します。

class Animal {
    func sound() -> String { "..." }
}
class Dog: Animal {
    override func sound() -> String { "Woof" }
}
class Cow: Animal {
    override func sound() -> String { "Moo" }
}

let farm: [Animal] = [Dog(), Cow(), Dog()]
for a in farm { print(a.sound()) }

出力:

Woof
Moo
Woof

Swift は、実行時に実際のオブジェクトに基づいて、どの実装を実行するかを決定します。変数の宣言された型は重要ではありません。重要なのはオブジェクトの型です。

class Animal {
    func sound() -> String { "..." }
}
class Cat: Animal {
    override func sound() -> String { "Meow" }
}

let pet: Animal = Cat()
print(pet.sound())

出力:

Meow

プロトコルは、構造体と列挙型に同じ柔軟性を与えます。ここでは、ある関数が任意の Drawable 値のリストを出力します。

protocol Drawable {
    func draw() -> String
}
struct Line: Drawable {
    let length: Int
    func draw() -> String { String(repeating: "-", count: length) }
}
struct Box: Drawable {
    func draw() -> String { "[ ]" }
}

func render(_ items: [any Drawable]) -> String {
    items.map { $0.draw() }.joined(separator: " ")
}

print(render([Line(length: 3), Box(), Line(length: 1)]))

出力:

--- [ ] -

ポリモーフィズムは、さまざまな種類のものに対する長いif/switchチェーンを置き換えます。値が何であるかを尋ねてから何をするかを決めるのではなく、値自身に実行させます。新しい種類を追加する場合は、すべてのswitchを編集するのではなく、新しい型を追加します。

// ポリモーフィズムなし
if kind == "dog" { print("Woof") } else if kind == "cow" { print("Moo") }

// ポリモーフィズムあり
for animal in farm { print(animal.sound()) }
challenge icon

チャレンジ

簡単

Animal には name、legs()(4)および describe() があり、legs() と sound() から組み立てられた Rex has 4 legs and says Woof を返します。legs() と sound() のみをオーバーライドして、Dog(sound Woof)、Bird(2 legs、sound Tweet)、Snake(0 legs、sound Hiss)を宣言してください。

提供されたコードは、dog,Rex、bird,Pip、または snake,Kaa の行を読み込み、動物を1つの [Animal] 配列に格納して、それぞれに対して describe() を出力します。

コードは Animal.swift、Dog.swift、Bird.swift、Snake.swift に記述してください。main.swift には提供された入出力コードが含まれており、編集できません。

自分で試してみよう

// 提供された入出力コード: そのままにしておく
var input: [String] = []
while let line = readLine() { input.append(line) }
var zoo: [Animal] = []
for line in input {
    let p = line.split(separator: ",").map(String.init)
    switch p[0] {
    case "dog": zoo.append(Dog(name: p[1]))
    case "bird": zoo.append(Bird(name: p[1]))
    default: zoo.append(Snake(name: p[1]))
    }
}
for a in zoo { print(a.describe()) }
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Swiftプレイグラウンド