継承よりもコンポジション
Goの設計思想を理解します
「継承よりもコンポジション」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。
Goの設計思想
Goでは、クラス継承を意図的に採用していません。慣用的な方法はコンポジションです。小さな型やインターフェースを組み合わせて振る舞いを構築します。
継承を使わない理由
深い継承ツリーは壊れやすいものです。基底クラスの変更が予測できない形で波及するためです。コンポジションなら、関係を明示的かつ柔軟に保てます。
is-aよりhas-a
「Manager は Employee です」とモデル化するのではなく、「Manager は Employee のデータと機能を埋め込みやフィールドによって 持ちます」とモデル化します。
package main
import "fmt"
type Employee struct{ Name string }
func (e Employee) Work() string { return e.Name + " works" }
type Manager struct {
Employee
Reports int
}
func main() {
m := Manager{Employee{"Lin"}, 3}
fmt.Println(m.Work(), "-", m.Reports, "reports")
}インターフェースに対してプログラミングする
小さなインターフェースで振る舞いを定義し、それを受け取るようにします。実装を相互に入れ替えられるため、差し替えやモック化も簡単です。
package main
import "fmt"
type Notifier interface{ Notify(msg string) }
type Email struct{}
func (Email) Notify(msg string) { fmt.Println("email:", msg) }
func alert(n Notifier, m string) { n.Notify(m) }
func main() {
alert(Email{}, "deploy done")
}実装の差し替え
関数がインターフェースに依存しているため、関数を変更せずに任意の実装を渡せます。
package main
import "fmt"
type Notifier interface{ Notify(msg string) }
type Email struct{}
type SMS struct{}
func (Email) Notify(m string) { fmt.Println("email:", m) }
func (SMS) Notify(m string) { fmt.Println("sms:", m) }
func alert(n Notifier, m string) { n.Notify(m) }
func main() {
alert(Email{}, "hi")
alert(SMS{}, "hi")
}振る舞いの組み合わせ
複数の小さなコンポーネントを埋め込み、独立してテストできる部品から機能豊富な型を組み立てます。
package main
import "fmt"
type Logger struct{}
func (Logger) Log(s string) { fmt.Println("log:", s) }
type Cache struct{ data map[string]string }
func (c Cache) Get(k string) string { return c.data[k] }
type Service struct {
Logger
Cache
}
func main() {
s := Service{Cache: Cache{data: map[string]string{"k": "v"}}}
s.Log("started")
fmt.Println(s.Get("k"))
}依存性の注入
依存関係をハードコーディングするのではなく、インターフェースとしてコンストラクターに渡します。これは、配線にコンポジションを適用したものです。
package main
import "fmt"
type Store interface{ Save(s string) }
type MemStore struct{ items []string }
func (m *MemStore) Save(s string) { m.items = append(m.items, s) }
type App struct{ store Store }
func NewApp(s Store) *App { return &App{store: s} }
func main() {
app := NewApp(&MemStore{})
app.store.Save("x")
fmt.Println("saved")
}小さなインターフェースが有利
インターフェースが小さいほど、それを満たす型が増え、テストもしやすくなります。インターフェースが大きいほど、抽象化は弱くなります。
壊れやすい基底クラスを避ける
継承を使わなければ、壊れる基底クラスもありません。各コンポーネントが独立して進化するため、結合を減らせます。
インターフェースを受け取り、構造体を返す
Goでよく使われる指針です。関数はインターフェース(柔軟な入力)を受け取り、具体的な構造体(明確で使いやすい出力)を返します。
コンポジションのチェックリスト
- is-aではなくhas-aとしてモデル化する
- 小さなコンポーネントを埋め込む
- 小さなインターフェースに依存する
- 依存関係を注入する
クイックチェック
コンポジションの考え方に関する知識を確認しましょう。
まとめ
Goにおけるコンポジションの考え方を学びました。
- 継承は使わず、埋め込みとインターフェースで組み合わせる
- is-aよりhas-aとしてモデル化する
- 小さなインターフェースに対してプログラミングし、依存関係を注入する
- インターフェースを受け取り、構造体を返す
よくある質問
「継承よりもコンポジション」レッスンは無料ですか?
はい。「継承よりもコンポジション」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。
「継承よりもコンポジション」で何を学びますか?
Goの設計思想を理解します ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Go Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「継承よりもコンポジション」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このGo Academyレッスンでコードを書いて実行できますか?
はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 構造体の埋め込み
- インターフェースの埋め込み
- メソッドプロモーション
- 継承よりもコンポジション