オブジェクト指向型言語(OOL)
中間試験 教科書ノート
東京都立大学 システムデザイン学部 情報科学科/西内信之 先生 | 第2回〜第7回 完全対応
この科目の全体地図
この科目は「プログラムをどう作ると、変更に強く・再利用しやすく・分かりやすくなるか」を学びます。前半(第2〜3回)で考え方(概念)を、後半(第4〜7回)でそれを Python で実装する方法を学ぶ、という一本道です。
オブジェクト指向の歴史・特徴・概念
2-1. 言語の進化(なぜOOが生まれたか)
| 段階 | 内容 | 特徴・解決したこと |
|---|---|---|
| 機械語 | 0/1のバイナリ。16進(0-9,A-F)で表記。1940年代・真空管 | コンピュータが直接解釈。人間には極めて難しい |
| アセンブリ言語 | 「ニーモニック」(命令コード)をアセンブラで機械語へ変換 | 記号で書ける最初の一歩。専門家向け・少し間違うと暴走 |
| 高水準(高級)言語 | コンパイラで翻訳し高速実行 | 複数の機械語をまとめた「高級な」文法 |
| 構造化言語 | 基本三構造でGOTOレス、サブルーチン導入 | スパゲッティコード回避・サブルーチンの独立性強化 |
| オブジェクト指向型言語(OOL) | データとコードをオブジェクトにまとめる | グローバル変数問題・貧弱な再利用を解決 |
GOTO文の乱用(=スパゲッティコード)を排除できる。2-2. オブジェクト指向(OOP)とは
互いに密接な関連を持つデータ(変数)とコード(メソッド)をひとつにまとめてオブジェクトとし、役割の異なるオブジェクトを相互に作用させてプログラム全体を構築するソフトウェア開発手法。
2-3. クラス 継承 ポリモーフィズム = 三大要素
| 要素 | 働き | 目的 | 覚え方(暗記) |
|---|---|---|---|
| クラス | 変数とメソッドをまとめて部品化 | 整理整頓 | まとめて、隠して、たくさん作る |
| 継承 | 重複するクラス定義を共通化 | 無駄を省く | クラスの共通部分を別クラスにまとめる |
| ポリモーフィズム | メソッドを呼び出す側を共通化 | 無駄を省く | 共通メインルーチンを作る |
2-4. 機能中心 vs モノ中心(カレーの例)
クラス・継承・ポリモーフィズム+カプセル化
3-1. オブジェクトを考える3つの観点
- 概念:オブジェクトは「責任」の集合
- 仕様:オブジェクトは「起動できるメソッド」の集合
- 実装:オブジェクトは「コードとデータ、その相互の演算処理」
3-2. クラスとインスタンス
3-3. カプセル化(情報隠蔽)
private(隠す)/public(公開)で区別。Pythonには基本的にこの区別はない。3-4. 継承
3-5. ポリモーフィズム
Python基礎:変数・条件・繰り返し・型
4-1. 算術演算子と変数
| 演算子 | 意味 | 例 |
|---|---|---|
+ - * / | 加減乗除 | 4 / 2 → 2.0 |
% | 剰余(余り) | 5 % 3 → 2 |
** | べき乗 | 6 ** 2 → 36 |
変数 = 値 は「右辺を左辺に代入」する意味で、「等しい」ではない。apple_price = 100
orange_price = 200
total = apple_price + orange_price
print(total) # 300
4-2. 予約語・命名規則(PEP-8)
- Pythonには 33個の予約語(
if for while def class True False None and or not import…)があり、変数名には使えない。 - 変数に使える文字=英大文字・小文字・数字・
_(アンダースコア)。ただし1文字目に数字は不可、予約語は不可、組み込み関数名と被らないよう注意。
_ → snake_case(例 my_function)。クラス名=大文字始まり、各単語の頭も大文字 → PascalCase(例 MyClass)。コメント
print("こんにちは") # 1行コメントは # 以降
"""
複数行コメントは
ダブルクォート3つで囲む
"""
4-3. 条件分岐(if / elif / else)
:、本体はインデント(字下げ)。これを忘れるとエラー。if 条件式1:
処理a
elif 条件式2: # elif は else if の略
処理b
else:
処理c
| 比較演算子 | > | >= | < | <= | ==(等しい) | !=(等しくない) |
|---|
4-4. 繰り返し(for / range)
for i in range(開始値, 終了値, 増減量):
処理
range(5) は 0,1,2,3,4。4-5. 型とリスト
- 数値型:整数 / 浮動小数点(
-2.0)/ 複素数(8+9j) - 文字列型:
'Hello'"Good bye"/論理型:TrueFalse - リスト型:
a = [50, 80, 100]。インデックスは0始まり - 辞書型
{}(見出し:データ)/タプル型()(書き換え不可)/集合型{}(順序なし・重複なし)
[[1,2,3],[4,5,6]] のようにリストの中にリスト。Python:関数
def add(x, y): # x, y は仮引数
"""xとyの和を返す""" # docstring(説明文)
return x + y # 返り値(戻り値)
result = add(2, 3) # 2, 3 は実引数 → result は 5
| 用語 | 意味 |
|---|---|
| 仮引数 | 関数を定義しているところに書く引数 |
| 実引数 | 関数を呼び出すところに書く引数 |
| 返り値(戻り値) | return で関数から返すデータ |
print() len()(長さ・要素数)max() min() sorted()(並べ替え)range() など。"""…""" で1行簡潔に(72文字まで/PEP 257)。Python:クラス実装
6-1. クラスを使うと何がうれしい?
- 整理できる:スマホ=全体プログラム、フォルダ=クラス、アプリ=関数 のように分類して探しやすい。
- 量産できる:1つの設計図(クラス)から、変数を変えていくつでもインスタンスを作れる。
6-2. 書式・インスタンス化
class クラス名(): # 授業ではクラス名に括弧を付ける
変数の定義
def メソッド名(self):
処理
ins = クラス名() # インスタンス化
ins.変数 # 変数の参照
ins.メソッド名() # メソッドの呼び出し
6-3. self(最重要)
self。これは「仮のインスタンス」を表す。メソッド呼び出し時、インスタンスが自動的に第1引数として渡されるため、書かないとエラーになる。呼び出す側では self は指定不要(第2引数以降を渡す)。self.変数 / self.メソッド() で内部にアクセスできる。class SampleClass():
def s_method1(self, message):
print(message)
def s_method2(self):
self.s_method1("Hello World!") # 内部メソッドを self で呼ぶ
ins = SampleClass()
ins.s_method2() # ⇒ Hello World!
6-4. コンストラクタ __init__
__init__)。第1引数は self、第2引数以降で初期値を受け取り、self.x = 引数 でインスタンス変数を設定する。class Example():
def __init__(self, a, b):
self.num1 = a
self.num2 = b
def print_tot(self):
print(self.num1 + self.num2)
myinstance = Example(1, 2)
myinstance.print_tot() # 3
Python:継承・クラス変数とインスタンス変数
7-1. クラス変数 と インスタンス変数
| 種類 | 性質 | クラス外部から | クラス内で |
|---|---|---|---|
| インスタンス変数 | インスタンスごとに独立 | インスタンス.変数 | self.変数 |
| クラス変数 | 全インスタンス共通 | クラス名.変数/インスタンス.変数 | self.変数(読み出し時のみ) |
7-2. 継承の書式とオーバーライド
class 親クラス名():
...
class 子クラス名(親クラス名): # 括弧の中に親クラス名 ← これが子クラスの目印
...
- 親子の見分け方:クラス名の括弧の中にクラス名が書かれているかどうか。
- オーバーライド=親で定義したメソッドを、子で同名メソッドとして上書き。
- 子から親メソッドを呼ぶ:
super().メソッド名()(Python3)/super(子クラス, self).メソッド名()(Python2)。
7-3. 総合例(Animal → Dog / Snake)
class Animal():
def __init__(self, legs):
self.legs = legs
def walk(self):
print("歩く")
def cry(self):
print("鳴く")
def get_legs_num(self):
print(self.legs)
class Snake(Animal):
def __init__(self, num):
print("へびです")
super().__init__(num) # 親のコンストラクタを呼ぶ
def walk(self): # オーバーライド
print("はう")
def cry(self):
print("シャー")
nyoro = Snake(0)
nyoro.walk() # はう
nyoro.cry() # シャー
nyoro.get_legs_num() # 0
過去の中間レポート課題+模範解答
課題(1) 関数 ドリンク会計
① 請求金額を計算する関数cal_bill。仮引数は「コーヒーの数」「ジュースの数」、返り値は請求金額。コーヒー=500円、ジュース=400円。
② 会計情報を表示する関数bill_inf。実引数は「テーブル番号(1〜10)」と「請求金額(=cal_billの返り値)」。実行すると「テーブル△の請求金額は、〇〇〇円です。」と表示。
③ テーブル番号10・コーヒー3杯・ジュース2杯でbill_infを実行。
模範解答を見る
def cal_bill(coffee, juice):
"""コーヒーとジュースの数から請求金額を返す"""
return coffee * 500 + juice * 400
def bill_inf(table, price):
"""テーブル番号と請求金額を受け取り会計を表示"""
print(f"テーブル{table}の請求金額は、{price}円です。")
bill_inf(10, cal_bill(3, 2))
# → テーブル10の請求金額は、2300円です。(500*3 + 400*2 = 2300)
※ f"..."(f文字列)が未習なら print("テーブル" + str(table) + "の請求金額は、" + str(price) + "円です。") でも可。
課題(2) クラス 銀行口座 BankAccount
①BankAccountクラスを作成。データ=口座番号(数値)・所有者名(文字列)・残高(数値)をコンストラクタの引数で持たせる。メソッド=「預け入れ」「引き出し」「詳細表示(全データ表示)」。
② インスタンス化して、口座番号=学修番号、名前=自分の苗字、残高=50000 で作成し、預け入れ・引き出しを自由な金額で実行。
模範解答を見る
class BankAccount():
def __init__(self, number, name, balance):
self.number = number
self.name = name
self.balance = balance
def deposit(self, amount): # 預け入れ
self.balance += amount
def withdraw(self, amount): # 引き出し
self.balance -= amount
def show(self): # 詳細表示
print(f"口座番号:{self.number} 名義:{self.name} 残高:{self.balance}円")
acc = BankAccount(12345678, "平本", 50000)
acc.deposit(10000) # 60000
acc.withdraw(3000) # 57000
acc.show() # 口座番号:12345678 名義:平本 残高:57000円課題(3) 継承 円 → 円柱(Circle → Cylinder)
① 円を表すCircleクラス。コンストラクタで半径を引数に取り、面積を計算するメソッドを作成(返り値=面積)。
②Circleを継承してCylinderクラスを作成。コンストラクタで半径と高さを引数に取り、半径は親のコンストラクタを呼んで設定。体積を計算するメソッドは親の面積メソッドを利用(面積×高さ)。
③ 半径5・高さ10でインスタンス化し、体積を表示。
模範解答を見る
class Circle():
def __init__(self, radius):
self.radius = radius
def area(self):
return self.radius ** 2 * 3.14 # 半径×半径×円周率
class Cylinder(Circle):
def __init__(self, radius, height):
super().__init__(radius) # 親に半径を設定(重要)
self.height = height
def volume(self):
return self.area() * self.height # 親のareaを利用(面積×高さ)
cy = Cylinder(5, 10)
print(cy.volume()) # 785.0(= 5*5*3.14 * 10)
super().__init__(radius) を呼び、体積計算で self.area()(親メソッド)を再利用している点が「継承を理解しているか」の核心。ここを自力で書けるように。課題の原本(スクリーンショット)を見る

用語集(定義問題そのまま対策)
| 用語 | 定義(太字を落とさず書く) |
|---|---|
| オブジェクト指向 | 関連するデータとメソッドをオブジェクトにまとめ、オブジェクト同士の相互作用でプログラムを構築する開発手法 |
| クラス | モノの設計図。属性(データ)と機能(メソッド)をまとめたもの |
| インスタンス | クラスから作られ、実際に動作する実体(モノ) |
| カプセル化 | 内部構造を隠蔽し、公開インターフェース経由で操作を制御する仕組み(情報隠蔽) |
| 継承 | クラスの共通点・相違点を整理し、共通部分を親クラスにまとめて再利用する仕組み |
| is-a関係 | 継承の親子関係。「子 is-a 親」(例:乗用車 is-a 車) |
| オーバーライド | 親クラスのメソッドを、子クラスで同名メソッドとして上書きすること |
| ポリモーフィズム | 処理対象が変わっても、処理する側を変更しなくてよい仕組み(多態性) |
| ソフトウェア危機 | 大規模化で複雑になり、担当者が離れると扱えず機能追加に多大なコストがかかる問題 |
| self | クラス内メソッドの第1引数。仮のインスタンスを表す(必須) |
| コンストラクタ | 生成時に1度だけ自動実行される初期化用の特殊メソッド __init__ |
| クラス変数 / インスタンス変数 | 全インスタンス共通の変数 / インスタンスごとに独立した変数(同名はインスタンス変数優先) |
最重要 早見表
- クラス整理整頓/「まとめて、隠して、たくさん作る」
- 継承
class 子(親):/オーバーライド/super() - ポリモーフィズム呼ぶ側を共通化/poly+morph+ism
- カプセル化情報隠蔽(Pythonにprivate/public区別なし)
- 構造化の残課題=グローバル変数・貧弱な再利用 → OOPが解決
self=第1引数・必須/__init__=生成時1度だけ- クラス変数=全体共通/インスタンス変数=個別(同名はインスタンス変数優先)
rangeは終了値を含まない/リストの添字は0始まり- 命名:関数・変数=snake_case、クラス=PascalCase
予想問題+解答
毎回の宿題(練習・演習問題)が出題パターンの軸。クリックで解答が開きます。
概念編
Q1. 言語の進化を5段階で並べ、構造化で解決できたことと残った課題を述べよ。
解答を見る
機械語→アセンブリ言語→高水準(高級)言語→構造化言語→オブジェクト指向型言語。構造化で解決=スパゲッティコード回避・共通サブルーチンによる再利用。残った課題=グローバル変数問題と貧弱な再利用性(OOPが解決)。Q2. 三大要素を挙げ、目的と覚え方を説明せよ。
解答を見る
クラス(整理整頓/まとめて隠してたくさん作る)、継承(無駄を省く/共通部分を別クラスにまとめる)、ポリモーフィズム(無駄を省く/呼び出す側を共通化)。Q3. カプセル化・is-a関係・インスタンス・ポリモーフィズム・ソフトウェア危機を説明せよ。
解答を見る
用語集(上)の定義の通り。特にカプセル化=情報隠蔽(公開インターフェース経由で操作)、is-a=継承の親子、ポリモーフィズム=処理する側を変えなくてよい仕組み。Q4. 構造化とOOPを「カレー」または「セミナー講師」の例で比較せよ。
解答を見る
構造化=手順を一直線に記述(簡単だが再利用×・変更が波及)。OOP=役割を持つオブジェクトが連携(再利用◯・変更の影響が小さいが学習難易度が高い)。講師の例なら、OOPでは学生オブジェクト自身が移動し、講師は指示するだけ。Python実装編
P1. 整数を入力し、偶数なら Even、奇数なら Odd を表示。
解答を見る
n = int(input())
if n % 2 == 0:
print("Even")
else:
print("Odd")P2. 1〜100の3の倍数の和(for+if)。
解答を見る
total = 0
for i in range(1, 101):
if i % 3 == 0:
total += i
print(total) # 1683P3. for の2重ループで「*」を階段状に5行表示。
解答を見る
for i in range(1, 6):
for j in range(i):
print("*", end="")
print()P4. 二次方程式の解を返す関数 quadratic(a,b,c)(複数解)。
解答を見る
def quadratic(a, b, c):
d = b**2 - 4*a*c
x1 = (-b + d**0.5) / (2*a)
x2 = (-b - d**0.5) / (2*a)
return x1, x2
print(quadratic(2, -13, 15)) # (5.0, 1.5)P5. 身長cm・体重kgからBMIを返す関数 calc_bmi。
解答を見る
def calc_bmi(height_cm, weight_kg):
"""身長cmと体重kgからBMIを返す"""
h = height_cm / 100
return weight_kg / (h ** 2)
print(calc_bmi(170, 65))P6. Humanクラス(weight=65、run で-5、eat で+5して表示)。tanakaで実行。
解答を見る
class Human():
weight = 65
def run(self):
self.weight -= 5
print(self.weight)
def eat(self):
self.weight += 5
print(self.weight)
tanaka = Human()
tanaka.run() # 60
tanaka.eat() # 65P7. Staffクラス(基本給5000+ボーナス)。salaryメソッド。abe(10000),suga(20000)。
解答を見る
class Staff():
def __init__(self, bonus):
self.bonus = bonus
def salary(self):
return 5000 + self.bonus
abe = Staff(10000)
print(abe.salary()) # 15000P8. Healthクラス(身長・体重をコンストラクタ引数に)でBMIを返す cal_bmi。
解答を見る
class Health():
def __init__(self, height, weight):
self.height = height
self.weight = weight
def cal_bmi(self):
h = self.height / 100
return self.weight / (h ** 2)
aso = Health(160, 65)
print(aso.cal_bmi())P9. Animalを継承したDog(cryをオーバーライド)。pochiで全メソッド実行。
解答を見る
class Animal():
legs = 4
def walk(self):
print("歩く")
def cry(self):
print("鳴く")
def get_legs_num(self):
print(self.legs)
class Dog(Animal):
def __init__(self):
print("犬です")
def cry(self):
print("わんわん")
pochi = Dog()
pochi.walk(); pochi.cry(); pochi.get_legs_num()P10. クラス変数とインスタンス変数の違いと、同名のときの優先順位。
解答を見る
クラス変数は全インスタンス共通(クラス名.変数)、インスタンス変数は個別(インスタンス.変数)。両方に同名があればインスタンス変数が優先される。直前チェックリスト
- 言語進化の5段階と、構造化の残課題(グローバル変数・再利用)を言える
- 三大要素を「目的+覚え方」で説明できる
- カプセル化・is-a・ポリモーフィズムを自分の言葉で説明できる
- クラスとインスタンスの違い(設計図と実体)を図で描ける
- if / for / range の書式(コロン・インデント)を手書きできる
- range が終了値を含まない/添字が0始まりを覚えた
- 命名規則(snake_case / PascalCase)を区別できる
- クラス定義・インスタンス化・
selfを手書きできる __init__でインスタンス変数を初期化できる- 継承
class 子(親):・オーバーライド・super()を書ける - クラス変数とインスタンス変数の違い・優先順位を説明できる