ポリモーフィックなコレクション
CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 44/107。
インターフェースの最も強力な用途の1つは、異なる型を同じコレクションに格納することです。インターフェース型のスライスには、そのインターフェースを満たす任意の値を格納できるため、関連性はあるものの異なる型をまとめて扱えます。
さまざまな図形を管理する必要がある状況を考えてみましょう。型ごとに個別のスライスを用意する代わりに、インターフェース型の単一のスライスを使用できます。
type Shape interface {
Area() float64
}
type Circle struct{ Radius float64 }
func (c Circle) Area() float64 { return 3.14159 * c.Radius * c.Radius }
type Rectangle struct{ Width, Height float64 }
func (r Rectangle) Area() float64 { return r.Width * r.Height }
func main() {
shapes := []Shape{
Circle{Radius: 5},
Rectangle{Width: 4, Height: 3},
Circle{Radius: 2},
}
for _, s := range shapes {
fmt.Printf("Area: %.2f\n", s.Area())
}
}
shapes スライスには、円と長方形の両方が格納されています。反復処理を行うと、各要素は実際の型に応じて Area() に応答します。これはコレクションに適用されたポリモーフィズムです。同じループですべての図形の型を一様に処理できます。
ポリモーフィックコレクションは、さまざまな項目を処理するシステムを構築する際に不可欠です。たとえば、メールや SMS メッセージを送信する通知システム、さまざまな敵の種類を更新するゲーム、複数のファイル形式を処理するドキュメントプロセッサなどがあります。コレクションは特定の型を気にしません。各要素が必要な振る舞いを提供することだけが重要です。
チャレンジ
簡単統一されたインターフェースを通じてさまざまな種類のタスクを処理するタスク管理システムを構築しましょう。さまざまなタスクの種類を作成し、それらをポリモーフィックなコレクションですべてまとめて処理します。
コードを3つのファイルに分けて整理します。
task.go:TaskinterfaceをDefineし、Summary() stringmethodを要求します。このinterfaceは、すべてのタスクの種類がfulfill mustするcommon contractになります。types.go: それぞれがTaskinterfaceをImplementする、3つの異なるタスクの種類をCreateします。BugFixにはID(string) とSeverity(string) のfieldsがあります。そのSummary()はBug #[ID] ([Severity])を返しますFeatureにはName(string) とPoints(int) のfieldsがあります。そのSummary()はFeature: [Name] - [Points] ptsを返しますDocumentationにはTopic(string) fieldがあります。そのSummary()はDocs: [Topic]を返します
main.go:Taskのスライスをacceptsし、各タスクのsummaryをそれぞれ1行にprintsする、PrintBacklogという名前のfunctionをCreateします。inputからタスクの詳細を読み取り、各タスクの種類をoneつずつCreateし、それらをすべて単一の[]TaskスライスにCollectして、PrintBacklogに渡します。
次のinputが提供されます。
- Line 1: Bug ID
- Line 2: Bug severity
- Line 3: Feature name
- Line 4: Feature points (integer)
- Line 5: Documentation topic
たとえば、1042、critical、Dark Mode、8、API Referenceが与えられた場合、outputは次のようになります。
Bug #1042 (critical)
Feature: Dark Mode - 8 pts
Docs: API Referenceここでの利点は、PrintBacklogがbug、feature、documentationごとに別々のロジックを必要としないことです。単にスライスを反復処理し、各要素でSummary()を呼び出します。各タスクの種類は独自の形式で応答し、ポリモーフィックなコレクションによって、多様な型を統一的に処理できることを示しています。
自分で試してみよう
package main
import (
"fmt"
)
// TODO: Task のスライスを受け取る PrintBacklog 関数を作成する
// そして各タスクの summary をそれぞれの行に出力する
func main() {
// 入力を読み取る
var bugID string
var bugSeverity string
var featureName string
var featurePoints int
var docTopic string
fmt.Scanln(&bugID)
fmt.Scanln(&bugSeverity)
fmt.Scanln(&featureName)
fmt.Scanln(&featurePoints)
fmt.Scanln(&docTopic)
// TODO: 各タスクタイプを1つずつ作成する (BugFix, Feature, Documentation)
// TODO: すべてのタスクを1つの []Task スライスにまとめる
// TODO: タスクのスライスを渡して PrintBacklog を呼び出す
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
1Go オブジェクト指向の基礎
外部ファイルGo ワークスペースとモジュールパッケージとインポート公開された名前と非公開の名前Go におけるオブジェクト指向入門クラスとしての構造体構造体へのメソッド定義ポインタレシーバと値レシーバ構造体の初期化コンストラクタ関数まとめ:簡易計算機8エラー処理とOOP
error インターフェースカスタムエラー型エラーラッピング (fmt.Errorf)センチネルエラーerrors.Is() と errors.As()Panic、Defer、Recover復習 - ファイルパーサー自分で練習してみよう: Goオンラインコンパイラ