0Pricing
Go Academy · レッスン

継承よりもコンポジション

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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 構造体の埋め込み
  2. インターフェースの埋め込み
  3. メソッドプロモーション
  4. 継承よりもコンポジション
← Go Academyに戻る