トレイト (英: Trait) は、コンピュータープログラミングでの概念であり、専らオブジェクト指向プログラミングで用いられている。トレイトはメソッドの集合体であり、クラスの機能を拡張するために使われる[1][2]。
トレイトは、(1)自身が定義+実装しているメソッドを継承先クラスに注入する役割と、(2)自身が定義だけしているメソッドを継承先クラスに叙述してそこで実装させる役割の双方を持っている。定義=メソッドシグネチャ、実装=メソッドコードである。トレイトの継承は、インクルードと言われることが好まれるがそうでない言語もある。トレイトのインクルードを扱う作法はミックスイン(mixin)と言われることが多いがそうでない言語もある。なお、ミックスインでもトレイトを扱っていない言語もある。
トレイトは2000年代にSmalltalk方言のSqueakで最初に実装が試されてから、各言語で様々な形態に解釈されて導入されている。トレイトは多重継承されることから、同様の機能であるインターフェースとよく対比されて説明される。インターフェースとの違いは以下のようになる。
- インターフェースがメソッドシグネチャのみを持つのに対して、トレイトはメソッド(定義+実装)とメソッドシグネチャの双方を持ち、またデータメンバを持つこともある。
- インターフェースはサブタイピングでクラスに継承させるのに対して、トレイトはサブタイピングでクラスに継承させるか、アドホック多相(英語版)でクラスにインクルードさせるの二通りに分かれる。
- インターフェースは記名的型付け(英語版)で識別されるのに対し、トレイトは構造的型付け(英語版)で識別されることが多い。
トレイトは合成(union)と交差(intersection)ができる。これも大きな特徴である。
- トレイトの合成は交換法則が成り立つ。即ち
S = A + B
とT = B + A
としてのS
とT
は同型トレイトと判定される。
- トレイトの合成は平坦化される。即ち
X = B + C
としてS = A + X
とし、またT = A + B + C
とすると、S
とT
は同型トレイトと判定される[3]。
また、専用の書式でメソッドを列挙しての”その場トレイト”を作成できる言語もある。”その場トレイト”は構造型(structural type)とも呼ばれており、合成と交差に利用できる。
トレイトは任意の数だけクラスに継承/インクルードさせることができる。ここでクラスの多重継承と同様に名前衝突や菱形継承問題が発生するが、それをより柔軟に解決できる方法をトレイトは備えている。それは以下のようなものである。
- 対称和(symmetric sum)- トレイトは合成できるので、多重継承を”その場合成トレイト”に置換できる。
- 非対称和(override / asymmetric sum)- トレイトのメソッドを継承/インクルード先のメソッドでオーバーライドして、メソッド実体を任意に入れ替えることができる。
- 別名化(alias)- 各メソッドをリネームした”その場トレイト”を継承対象に置換できる。
- 排除(exclusion)- トレイトは交差できるので、必要メソッド群を切り抜いて不要メソッド群を除外した”その場トレイト”を多重継承に置換できる。
冒頭で述べた通り、トレイトはメソッドの集合体なので、合成と交差と構造型を用いての要素メソッドの自由な組み替えによって多重継承問題に対応できる。
トレイトを採用
- Smalltalk - 最初のトレイトは Smalltalk 処理系のひとつである Squeak を使ってベルン大学のソフトウェア合成グループによって実装が試され[4]、その有効性が実証された[5]。Squeak にはその後、公式リリースにもトレイトが組み込まれ標準で利用可能となった。Squeak から派生した Pharo も同様。
- PHP - 5.4.0 からサポート[6]。
- Raku -「ロール」。Perl 5 では Moose モジュールで利用可能。なおロールの限定的な用途のみ「トレイト」と呼称し紛らわしい。
- JavaScript の Joose フレームワーク
- Ruby のモジュールのmix拡張(試作のみ)[7] - Ruby 2.0 向けの新機能として計画された[8]が運用上の問題が見つかり放棄された[9]。
トレイトの類似品/派生品を採用
- Racket - エンティティとしてのトレイトは無いが、ミクスインをトレイトのように振る舞わせる関数やマクロが整備されている。
- Curl - 抽象クラスを多重継承することでトレイトを実現することができる。
- Swift - protocol、extensionを利用することでトレイトを実現することができる[10]。
- Rust - トレイトを有し、型変数に対する制約をトレイトで指定したり、ユーザー定義型の演算子に対する振る舞いを設定するのに利用されるが、その運用に際しそもそも衝突を許さないので(Orphan rule)、メソッドの集合という意味を除きSchärliの想定した使われ方はされず、トレイトとしては別物(実装の記述できるインタフェース程度)と考える方が良い。
Rustの他にもトレイトと称する言語機能を有する静的型言語もあるが、その本質は従来のミクスインのままである(平坦化されない)。ただし平坦なトレイトを模したりミクスインの問題点を回避する拡張を施すなどの工夫により、トレイトに近い使い勝手を実現している場合もある。
- ^ Nathanael Schärli、Stéphane Ducasse、Oscar Nierstrasz、Andrew P. Black 共著、Traits: Composable Units of Behaviour. Proceedings of the European Conference on Object-Oriented Programming (ECOOP). Lecture Notes in Computer Science 誌、2743巻、Springer-Verlag、2003年、pp. 248-274
- ^ Stéphane Ducasse、Oscar Nierstrasz、Nathanael Schärli、Roel Wuyts、Andrew P. Black 共著: Traits: A mechanism for fine-grained reuse. ACM Trans. Program. Lang. Syst. 誌、28(2): 331-388 (2006)
- ^ Schärli, Nathanael; Ducasse, Stéphane; Nierstrasz, Oscar; Black, Andrew P. (2003). “Traits: Composable Units of Behaviour”. Proceedings of the European Conference on Object-Oriented Programming (ECOOP).. Lecture Notes in Computer Science 2743: 248–274. http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf.
- ^ Nathanael Schärli, Stéphane Ducasse, Oscar Nierstrasz, and Andrew P. Black. Traits: Composable Units of Behavior. Technical Report -2, Institut für Informatik, Universität Bern, Switzerland, November 2002
- ^ Andrew P. Black, Nathanael Schärli, and Stéphane Ducasse. Applying Traits to the Smalltalk Collection Hierarchy. Technical Report -2, Institut für Informatik, Universität Bern, Switzerland, November 2002
- ^ Marr, Stefan. “Request for Comments: Horizontal Reuse for PHP”. The PHP.net wiki. The PHP Group. 31 January 2011閲覧。
- ^ http://marc.info/?l=ruby-cvs&m=130685857122161
- ^ http://www.rubyist.net/~matz/20100617.html
- ^ https://ruby-trunk-changes.hatenablog.com/entry/20111003/ruby_trunk_changes_33379_33380
- ^ “Mixins and Traits in Swift 2.0”. 2022年2月10日閲覧。
- ^ http://www.scala-lang.org/node/126 A Tour of Scala: Traits
- ^ http://www.ibm.com/developerworks/java/library/j-scala04298.html The busy Java developer's guide to Scala: Of traits and behaviors
- ^ http://docs.groovy-lang.org/next/html/documentation/core-traits.html Groovy Language Documentation