プロパティ(プログラミング)
一部のオブジェクト指向プログラミング言語におけるプロパティは、フィールド(またはデータメンバー)とメソッドの中間の機能を持つ、特別な種類のクラスメンバーです。プロパティの読み書き構文はフィールドの場合と同様ですが、プロパティの読み書きは(通常)「getter」メソッドと「setter」メソッドの呼び出しに変換されます。フィールドのような構文は、多くのメソッド呼び出しよりも読み書きが容易です([要出典]) 。しかし、メソッド呼び出しを「内部的に」介在させることで、データの検証、 (GUI要素などの)アクティブな更新、あるいは「読み取り専用フィールド」と呼ばれるものの実装が可能になります。
言語サポート
プロパティをサポートするプログラミング言語には、ActionScript 3、C#、D、Delphi / Free Pascal、eC、F#、Kotlin、JavaScript、Objective-C 2.0、Python、Scala、Swift、Lua、Visual Basicなどがあります。
JavaやC++などの一部のオブジェクト指向言語ではプロパティがサポートされていないため、プログラマは代わりにアクセサメソッドとミューテーターメソッドのペアを定義する必要があります。[1] [要出典]
Oberon-2 は、オブジェクト変数の可視性フラグを使用する代替メカニズムを提供します。[引用が必要]
Groovyなど、 Java 仮想マシン用に設計された他の言語では、プロパティがネイティブにサポートされています。
C++にはファーストクラスプロパティはありませんが、演算子オーバーロードでエミュレートできます。[2]
また、一部の C++ コンパイラは、言語拡張としてファーストクラスプロパティをサポートしていることにも注意してください。[引用が必要]
- Microsoft Visual Studio、[3] GCC、llvm/clang [ 4]では、 C#
__declspec(property)と同様のプロパティが作成されます。 - Borland C++およびBorland/CodeGear/Embarcadero C++Builderではこの
__propertyキーワードが使用されています。[5]
多くのオブジェクト指向言語では、プロパティはアクセサメソッドとミューテーターメソッドのペアとして実装されますが、アクセスはパブリックフィールドと同じ構文で行われます。ペアからメソッドを省略すると、読み取り専用プロパティ、またはまれに書き込み専用プロパティが生成されます。
プロパティの組み込みサポートを持たない言語では、同様の構造を単一のメソッドとして実装し、呼び出し時のコンテキストに応じて基になるデータを返すか変更するかを選択できます。このような手法は、例えばPerlで使用されています。[要出典]
一部の言語 ( Ruby、Smalltalk ) では、通常の方法 (場合によっては限られた量の構文糖)を使用して、プロパティのような構文を実現します。
構文のバリエーション
一部の言語では、プロパティとメソッドを正式に指定および使用するために、確立された構文規則に従います。
これらの条約の中には次のようなものがあります:
- ドット表記
- 括弧表記
ドット表記
次の例は、JavaScript でのドット表記を示しています。
ドキュメント.createElement ( "pre" ) ;括弧表記
次の例は、JavaScript での括弧表記を示しています。
ドキュメント[ "createElement" ]( "pre" );構文例
C#
クラスPen { private int color ; //プライベートフィールド//パブリックプロパティpublic int Color { get { return this.color ; } set { if ( value > 0 ) { this.color = value ; } } } } // アクセス: Pen pen = new (); int colorTmp = 0 ; // ... pen . Color = 17 ; colorTmp = pen . Color ; // ... pen . Color = ~ pen . Color ; // ビット補数... // もう一つの馬鹿げた例: pen . Color += 1 ; // "pen.set_Color(pen.get_Color() + 1)" よりずっと明確です! 最近のC#バージョンでは、「自動実装プロパティ」もサポートされています。これは、プロパティのバッキングフィールドがコンパイル時にコンパイラによって生成されることを意味します。つまり、プロパティにはセッターが必要です。ただし、セッターはプライベートにすることができます。
クラスShape { public int Height { get ; set ; } public int Width { get ; private set ; } } C++
C++にはファーストクラスプロパティはありませんが、ある程度まではプロパティをエミュレートする方法がいくつかあります。そのうちの2つを以下に示します。
標準C++の使用
stdをインポートします。 std :: same_asを使用します。 template < typename T > class Property { T value ; public : // T と T2 が同じ型であることを確認しますtemplate < typename U > requires same_as < T , U > T & operator = ( const U & i ) { value = i ; return * this ; } // 暗黙的に T への変換を行います。operator T const & ( ) const { return value ; } }; struct Foo { // 名前のないクラスを使用するプロパティ。class { private : int value ; public : int & operator = ( const int & i ) { return value = i ; } int operator int () const { return value ; } } alpha ; クラス{ private : float value ; public : float & operator = ( const float & f ) { return value = f ; } float operator float () const { return value ; } }ブラボー; }; struct Bar { // Property<> テンプレートを使用します。Property < bool > alpha ; Property < unsigned int > bravo ; }; int main ( int argc , char * argv []) { Foo foo ; foo . alpha = 5 ; foo . bravo = 5.132f ; Bar bar ; bar . alpha = true ; bar . bravo = true ; // この行は、ガード テンプレート メンバー関数のため、コンパイル時エラーが発生します。std :: println ( "{}, {}, {}, {}" , foo . alpha , foo . bravo , bar . alpha , bar . bravo ); return 0 ; } C++、Microsoft、GCC、LLVM/clang、C++Builder 固有
MSDN ドキュメント ページから改変した例。
// declspec_property.cpp構造体 Integer { int値; void setValue ( int j ) noexcept { value = j ; } [[ nodiscard ]] int getValue () const noexcept { return i ; } __declspec (プロパティ( get = getValue 、put = setValue )) int prop ; }; int main () {整数s ; s . prop = 5 ; 0を返す; } D
class Pen { private int myColor ; // プライベートフィールド// パブリックプロパティを取得public int color () { return myColor ; } // パブリックプロパティを設定public void color ( int value ) { myColor = value ; } } Pen pen = new Pen ; pen . color = ~ pen . color ; // ビット補数 // set プロパティは、通常の割り当てと同様に、式でも使用できますint theColor = ( pen . color = 0xFF0000 ); D バージョン 2 では、各プロパティ アクセサまたはミューテーターは @property でマークする必要があります。
class Pen { private int myColor ; // プライベートフィールド// パブリックプロパティを取得@property public int color () { return myColor ; } // パブリックプロパティを設定@property public void color ( int value ) { myColor = value ; } } Delphi/フリーパスカル
type TPen = class private FColor : TColor ; function GetColor : TColor ; procedure SetColor ( const AValue : TColor ) ; public property Color : Integer read GetColor write SetColor ; end ; 関数TPen.GetColor : TColor ; begin Result : = FColor ; end ; 手順TPen 。SetColor ( const AValue : TColor ) ; begin if FColor <> AValue then FColor := AValue ;終わり; // アクセス: var Pen : TPen ; // ... Pen . Color := not Pen . Color ; (* DelphiとFree Pascalも「直接フィールド」構文をサポートしています -プロパティ Color: TColor 読み取り、FColor 書き込み、SetColor;またはプロパティ Color: TColor 読み取り、GetColor 書き込み、FColor;コンパイラはフィールドの読み書きと全く同じコードを生成します。これにより、フィールドの効率性とプロパティの安全性が両立します。 (プロパティへのポインタを取得することはできません。また、メンバーアクセスはメソッド呼び出しに置き換えることができます。) *)電子
class Pen { // プライベート データ メンバーColor color ; public : // パブリック プロパティproperty Color color { get { return color ; } set { color = value ; } } } Pen blackPen { color = black }; Pen whitePen { color = white }; Pen pen3 { color = { 30 , 80 , 120 } }; Pen pen4 { color = ColorHSV { 90 , 20 , 40 } }; F#
型Pen ()=クラスlet mutable _ color = 0 メンバーthis . Colorでget () = _ color 、set value = _ color <- value end pen = new Pen ( )としますpen.Color < - ~~~ pen.Color JavaScript
function Pen () { this . _color = 0 ; } // Pen 型自体にプロパティを追加します。インスタンスごとに個別に設定することもできます。 Object . defineProperties ( Pen . prototype , { color : { get : function () { return this . _color ; }, set : function ( value ) { this . _color = value ; } } }); var pen = new Pen (); pen . color = ~ pen . color ; // ビット補数pen . color += 1 ; // 1 を加算 アクションスクリプト3.0
パッケージ{パブリッククラスPen {プライベートvar _color : uint = 0 ;パブリック関数get color (): uint { return _color ; }パブリック関数set color ( value : uint ): void { _color = value ; } } } var pen : Pen = new Pen (); pen . color = ~ pen . color ; // ビット補数pen . color += 1 ; // 1 を加算 Objective-C 2.0
@interface Pen : NSObject @property ( copy ) NSColor * colour ; // "copy" 属性により、オブジェクトのオリジナルではなくコピーが保持されます。 @end @implementation Pen @synthesize colour ; // アクセサメソッドを合成するためのコンパイラディレクティブ。// Xcode 4.5以降ではそのまま残すことができます。@end 上記の例は、次のように任意の方法で使用できます。
Pen * pen = [[ Pen alloc ] init ]; pen . colour = [ NSColor blackColor ]; float red = pen . colour . redComponent ; [ pen . colour drawSwatchInRect : NSMakeRect ( 0 , 0 , 100 , 100 )]; PHP
クラス Pen { プライベート int $color = 1 ; 関数 __set ( $property 、 $value ) { if ( property_exists ( $this 、 $property )) { $this -> $property = $value ; } } 関数 __get ( $property ) { if ( property_exists ( $this 、 $property )) { return $this -> $property ; } return null ; } }$p = new Pen (); $p -> color = ~ $p -> color ; // ビット補数echo $p -> color ;パイソン
プロパティは、新しいスタイルのクラス(スーパークラスobjectとしてを持つクラス)でのみ正しく機能し、Python 2.2以降でのみ利用可能です(チュートリアル「Python 2.2における型とクラスの統合」の関連セクションを参照)。Python 2.6では、プロパティを定義するためのデコレータを含む新しい構文が追加されました。
class Pen : _color : int # "プライベート"変数 def __init__ ( self ) -> None : self . _color = 0 @property def color ( self ) -> int : self . _color を返します @color . setter def color ( self , color : int ) -> None : self . _color = color pen : Pen = Pen () # アクセス: pen . color = ~ pen . color # ビット補数 ...ルビー
class Pen def initialize @color = 0 end # @colorフィールドのゲッターを定義しますdef color @color end # @colorフィールドのセッターを定義しますdef color= ( value ) @color = value end end pen = Pen . new pen . color = ~ pen . color # ビット補数 Ruby は、クラスのインスタンス メソッドとして定義された自動 getter/setter シンセサイザーも提供します。
class Pen attr_reader :brand # @brand の getter を生成します (読み取り専用) attr_writer :size # @size の setter を生成します (書き込み専用) attr_accessor :color # @color の getter と setter の両方を生成します (読み取り/書き込み) def initialize @color = 0 # オブジェクト内ではインスタンス変数に直接アクセスできます@brand = "Penbrand" @size = 0 . 7 # ただし、attr_accessorクラスインスタンスメソッドで定義されたsetterメソッドを使用することもできますend end pen = Pen . new puts pen . brand # 生成されたゲッターを介してペンのブランドにアクセスしますpen . size = 0 . 5 # 生成されたセッターを介してペンのサイズフィールドを更新しますpen . color = ~ pen . color ビジュアルベーシック
Visual Basic (.NET 2003~2010)
Public Class Pen Private _color As Integer ' プライベートフィールド Public Property Color () As Integer ' Public property Get Return _color End Get Set ( ByVal value As Integer ) _color = value End Set End Property 授業終了 ' ペンクラスのインスタンスを作成するDim pen As New Pen () 'ペンの値を設定します。色= 1 ' 値を取得するDim color As Int32 = pen . Color Visual Basic (.NET 2010 のみ)
パブリッククラスペン パブリックプロパティColor () AsInteger 'パブリックプロパティ 授業終了 ' ペンクラスのインスタンスを作成するDim pen As New Pen () 'ペンの値を設定します。色= 1 ' 値を取得するDim color As Int32 = pen . Color ビジュアルベーシック6
' は clsPen というクラスにありますPrivate m_Color As Long パブリックプロパティGet Color () As Long Color = m_Color Endプロパティ パブリックプロパティLet Color ( ByVal RHS As Long ) m_Color = RHS Endプロパティ ' アクセス中: Dim pen As New clsPen ' ... pen . Color = Not pen . Color 参照
- 変数(コンピュータサイエンス)
- 属性(オブジェクト指向プログラミング)
- バインドされたプロパティ
- 分野(コンピュータサイエンス)
- インデクサー(プログラミング)
- 方法(コンピュータプログラミング)
- ミューテーターメソッド
- 均一アクセス原則
参考文献
- ^ 「Javaのアクセサとミューテーター」C#コーナー - ソフトウェアおよびデータ開発者コミュニティ. 2022年1月5日閲覧。
- ^ 「ネイティブC++プロパティの移植性」. Stack Overflow . Stack Overflow . 2022年1月5日閲覧。
- ^ "property (C++)". Microsoft 技術ドキュメント. Microsoft . 2022年1月5日閲覧。
- ^ "clang::MSPropertyDecl クラスリファレンス". Clang: LLVM の C 言語ファミリフロントエンド. 2022年1月5日閲覧。
- ^ "__property キーワード拡張". Embarcadero/IDERA ドキュメント Wiki . 2022年1月5日閲覧。