私なりのオブジェクト指向プログラミングの定義
きしださんの以下のツイート
オブジェクト指向はこの20年だれも再定義せずみんな自分の思うオブジェクト指向を暗黙に仮定して適当に話してるだけなので、技術的な共通認識のもとの議論はほとんどできないんですよ。という話を「オブジェクト指向をきちんと使いたいあなたへ」の記事に書いたのだけど、そろそろ公開するか
— きしだൠ(K8S(Kishidades)) (@kis) July 29, 2019
を読んで、そういえば、私が思うオブジェクト指向の定義、についてツイッター以外ではあまり語ったことがなかったなと思い返し、ちょっと記事にしてみることにしました。まず、結論からいうと、私はオブジェクト指向プログラミングとは
- サブタイピングを活用したプログラミング手法の総称
と考えています。ここで、クラス継承とかインタフェース継承とかダックタイピングとかではなく、単にサブタイピングであるのがポイントです。なお、型がない言語(Ruby、JavaScript、などなど)についても、実際にプログラミングをしているときは、たとえば「あるオブジェクトはメソッドm1, m2, ...を持っている」と仮定してコードを書いているはずだと思うので、それらは構造的部分型のようなものを使っているものとして考えます。
ここで、クラスもインタフェースも状態のカプセル化も一切でてこないことに違和感を抱かれる方もいると思うので説明します。まず、いわゆるオブジェクト指向プログラミング言語(言語の中でオブジェクトシステムを定義しているもの含む)には非常に様々なものがある、というのが重要です。簡単に分類しただけでも
- クラスをベースにしたオブジェクト指向プログラミング言語: C++、Java、C#、Scala、Ruby、
- オブジェクトをベースにしたオブジェクト指向プログラミング言語: Self、JavaScript、TypeScript、Go
- それ以外のオブジェクトシステム(主にマルチメソッドをサポートするもの):CLOS、Nice、Julia
といったものが思い浮かびます。3番目のものは、いわゆるオブジェクト指向プログラミングの主流派からは外れていますが、個人的にはそれらも含めて考えたいところです。これらの言語のすべてに共通する特徴を考えたときに残るのがサブタイピング(ないし極めて近い概念)を持っているということが挙げられます。というわけで、最大公約数を取ったときにはそうなるだろう、というのが私の結論です。
もちろん、主流のオブジェクト指向プログラミング言語(C++、Javaなど)ではクラスを活用すると思いますが、今やTypeScript(オブジェクトベースかつ、構造的部分型を使った型付け)も非常によく使われるようになってきていますし、それを無視してオブジェクト指向プログラミングを論じるのも無理筋だと思います。さらに、Scalaでよく行われるような、不変オブジェクトとメソッドを組み合わせたプログラミングスタイルも珍しいものではないわけで、可変状態ですら必須でないと言えます。
このように考えたときに、どうしても最後まで残らざるを得ないのがサブタイピングだと考えます。私が挙げた上記の言語すべてがそれらの概念(あるいは極めて近い概念)を持っています。とはいえ、普段、私がオブジェクト指向プログラミングとして意識するのは、クラスベースのオブジェクト指向プログラミング(特にできるだけ状態を不変にする)だったりするのですが、それはおいておきます。また、ここでは、私が思うオブジェクト指向プログラミングの定義について述べましたが、他の人がそれと違った定義をもっていてもいいと思います。
ただ、万人に共通するオブジェクト指向プログラミングのイメージというのは、おそらくもはや存在しないので、それぞれが違うイメージを持っていると認識した上で、定義をすりあわせた上で議論することが重要かなと思います。