カウンタクラス(機能合成)
カウンタクラス(機能合成)
このレッスンで分かること
- オブジェクトの本質は「
データ(状態) と振る舞い(操作) を一体化させる」点にあるOOPの最大の特徴は、クラスが状態(state) を持てる ことですCounterクラスには次の機能を持たせます
カウンタクラス とは
状態を持つカウンタを
クラスで実装し、counterOps(ops)でinc/dec/resetの操作を順に適用して最終値を返す。
OOP の最大の特徴は、クラス が 状態 (state) を持てる ことです。関数 だけで書くと、状態を 引数 と 戻り値 で持ち回さなければなりませんが、クラス の インスタンス は内部の 属性 に 状態 を保持できます。本レッスンでは、最もシンプルな状態保持の例として カウンタ を実装します。
オブジェクトの本質は「
データ(状態) と振る舞い(操作) を一体化させる」点にある。
Counter クラスの設計
Counter クラスには次の機能を持たせます。
属性—value(現在のカウント値、初期 0)inc()—valueを 1 増やすdec()—valueを 1 減らすreset()—valueを 0 に戻すcurrent()— 現在のvalueを返す
Python
class Counter:
def __init__(self):
self.value = 0
def inc(self):
self.value += 1
def dec(self):
self.value -= 1
def reset(self):
self.value = 0
def current(self):
return self.value5 つのメソッドを 1 つの クラス にまとめることで、「カウンタ として振る舞うオブジェクト」を作れます。Counter() でインスタンスを作るたびに、独立した 状態 を持つカウンタが生まれます。
インスタンスは独立
Python
c1 = Counter()
c2 = Counter()
c1.inc()
c1.inc()
c2.inc()
print(c1.current()) # 2
print(c2.current()) # 1c1 と c2 はそれぞれ別のオブジェクトで、value 属性も別々に持ちます。これが グローバル変数 と違うところで、複数の カウンタ を同時に動かせます。
操作列を適用する流れ
操作列を順に適用するパターンを図にすると次のとおりです。
図のポイント (テキスト併記)
- 各操作は
インスタンスのvalueを更新する副作用を持ちます
各操作は インスタンス の value を更新する 副作用 を持ちます。関数型 プログラミングでは 副作用 を避ける傾向がありますが、OOP では「オブジェクトの状態を変える のは、そのオブジェクトのメソッドだけ」というルールで 副作用 をコントロールします。これを カプセル化 と呼びます。
JavaScript での実装
JavaScript
class Counter {
constructor() {
this.value = 0;
}
inc() { this.value += 1; }
dec() { this.value -= 1; }
reset() { this.value = 0; }
current() { return this.value; }
}Java でも同じ構造で書けますが、本問では Python と JavaScript のみ対応します。
このレッスンでやること
関数 counterOps(ops) を実装してください。ops は文字列の配列で、各要素は "inc" / "dec" / "reset" のいずれか。Counter クラスを内部で作り、ops を順に適用した後、最終的な value を 整数 で返します。例として ["inc", "inc", "dec", "inc"] → 2、["inc", "inc", "reset"] → 0。
よくある間違い
self.value = 0をCounter.value = 0と書いてしまう (クラス変数になり、全インスタンスで共有される)。incの中でvalue += 1(self なし) と書いて、ローカル変数を 1 にして終わる。self.value += 1が正解。- 戻り値を
配列にしてしまう。本問では最終値の整数だけを返す。
カプセル化のメリット
カプセル化は、状態を外から直接いじれないようにし、メソッド経由でしか変更できなくする原則だ。
Counter クラスを使う側は、内部の value 属性を直接書き換えるのではなく、inc() や reset() を呼びます。これによって、カウンタ の振る舞いが「プラス 1」「マイナス 1」「ゼロに戻す」の 3 種類だけに限定され、予期しない値の代入を防げます。Java などの言語では private キーワードで属性へのアクセスを文法的に制限できます。Python は文法的な強制はありませんが、慣例として _value (アンダースコア始まり) を「外から触らないでね」のサインに使います。
状態を直接いじれる場所が増えるほど、
バグの原因も増える。カプセル化は「バグの出口を狭める」設計原則だ。
やってみよう
OOP の「状態 + 操作」のセットを、Counter という最小例で体感してください。スタック キュー も、突き詰めれば「状態 = items 配列、操作 = push/pop など」という同じパターンの応用です。
よくある質問
Q. このトピックは実務でどう役立ちますか?
A. DB のクエリ最適化、API 設計、データ構造の選択など、設計判断の根拠になります。表面的にライブラリを使うだけでなく「なぜそれが速いのか」を理解できると、性能問題を未然に防げます。コーディング面接でも頻出のテーマです。
Q. 計算量はどう求めれば良いですか?
A. ループのネストごとに掛け算する、再帰なら漸化式から解く、というのが基本です。Big-O 表記は定数倍と低次の項を無視するため、n の指数(n²、n log n など)に注目してください。最悪・平均・最良の 3 つを意識すると説得力が増します。
Q. 覚えるべき定番アルゴリズムは何ですか?
A. 二分探索、クイックソート/マージソート、BFS/DFS、ダイクストラ、DP の基本問題(フィボナッチ・ナップサック)が必修です。これらを「白紙から書ける」状態にすると、応用問題が一気に解けるようになります。
次のレッスン
次は 第 5 章クイズ — クラスと OOP で、第 5 章クイズ — クラスと OOP を学びます。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- カウンタクラス の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. カウンタクラス とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
要件
- 関数
counterOps(ops)を実装し、最終的なカウンタ値を整数で返す - 内部に
Counterクラスを定義し、value属性とinc/dec/resetメソッドを持たせる - ops を 1 つずつ取り出し、対応するメソッドを呼ぶ
入出力例
test-cases.txt
counterOps(["inc","inc","dec","inc"]) → 2
counterOps(["inc","inc","reset","inc"]) → 1
counterOps(["inc","inc","inc","reset"]) → 0
counterOps(["dec","dec","dec"]) → -3
counterOps([]) → 0
counterOps(["inc","inc","inc","inc","inc"]) → 5