2021-02-28

『オブジェクト指向入門 第2版』の8章を読んだ

第8章 実行時の構造:オブジェクト

定義:オブジェクト

オブジェクトは何らかのクラスの実行時のインスタンスである.

オブジェクトはフィールドの集合である.ただし,フィールドには何らかの制約(クラス不変表明)が存在することがある.

基本型でないフィールドをサブオブジェクトと呼ぶ.例えば,BookクラスのフィールドにWriterクラスのオブジェクトが存在するとき,Writerオブジェクトはサブオブジェクトである.

class Book {
	title: string
  date, page_count: integer
  writer: Writer // サブオブジェクト
}

BookオブジェクトがWriterオブジェクトを持つとすると,ある著者が複数の本を書いている場合でも,Bookオブジェクトそれぞれに同じ内容のWriterオブジェクトを持たせなければならない.この無駄を省くために,writerにはオブジェクトそのものではなく,参照を持たせることが考えられる.

定義:参照

参照とは実行時にvoid(無効)かアタッチ状態(attached)かのいずれかの値をとる.アタッチ状態の場合,参照は1つのオブジェクトを示す.(その場合,その参照はその特定のオブジェクトにアタッチされているという).

1つのWriterオブジェクトを複数のBookオブジェクトが参照することで,フィールドの値が同じのWriterオブジェクトの重複を避けられる.

生成プロシージャ

生成プロシージャは,オブジェクトの生成時にフィールドを初期化するためのプロシージャ.JavaやC++における生成プロシージャはコンストラクタである.これらの言語の生成プロシージャはすべて同じ名前のため,シグネチャで区別しないと異なる生成プロシージャを呼べない.


多重定義ができる言語なら,生成プロシージャがすべて同じ名前でも,シグネチャによって呼ぶ生成プロシージャを変更できる.多重定義ができず,生成プロシージャの名前が決まっている場合は,引数の型によって分岐させることで異なる初期化に対応できる.

以下のコードは静的メソッドで異なる初期化をやったもの. __new__ -> __init__ -> make_* という処理になっている.生成命令に当たるのが__new__で,生成プロシージャは__init__だと思う.「オブジェクト生成時に実行するプロシージャ」が生成プロシージャなら,静的メソッドで生成したオブジェクトを返すのは,生成プロシージャプロシージャ……? 実質生成呼び出しになっている……?

そもそもpythonで考えても意味ないかな?

class A:
    @staticmethod
    def make_x():
        a = A()
        a.x = 'x';
        return a


    @staticmethod
    def make_y():
        a = A()
        a.y = 'y';
        return a

a = A.make_x();
print(a.x)  # x
a = A.make_y();
print(a.y)  # y

参照型と拡張型

参照型であるクラスCがある.C型のエンティティは,C型のインスタンスにアタッチされうる参照を表す.拡張型であるクラスEがある.E型のエンティティは,E型のインスタンスを直接表す.参照型は特定のインスタンスを「知っている」ことを表し,拡張型は特定のインスタンスを「持つ」ことを表す.

Javaでいうところの,プリミティブ型と参照型?

オブジェクト指向分析は現実世界をモデリングするわけではない

(ここあまり理解ができていない)

  1. 第1に,現実は見る人の目の中にある.

  2. 既存の手続きにコンピュータとソフトウェアが取り入れられており,「現実の世界」と「ソフトウェア」を独立した実態として扱えない.

  3. 一部のソフトウェアでは現実世界という概念がない
    例えば,コンパイラは何らかのプログラムを扱うが,そのプログラムは現実世界に存在しているわけではない.扱うものが,必ずしも現実世界に存在するものとは限らない.

  4. ソフトウェアシステムは現実のモデルではなく,「現実の部分的なモデル」のモデルである.
    金融情報システムは株取引のモデルではなく,ある会社が自身の目的を達成するために考え出したモデルをソフトウェアにしたものである.