PHPにアクセサメソッドというものがあると思いますが、その意義がわかりません。
一般的な解説には「プロパティのアクセス修飾子をprivateにすると、不正なデータは外部から格納できなくなり安全ですが、そのプロパティに対して外部からデータを入出力できるようにする必要があります。」という文章があります。
そもそも外部から不正なデータを遮断することで安全性を確保するためのprivateなのに、「そのプロパティに対して外部からデータを入出力できるようにする」ことができてしまうと、意味がないように思えるのです。
なぜprivateにする必要があるのか。そして、どうしてprivateを使えば安全にデータを読み書きできるのかを教えてください。
よろしくお願い致します!
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

退会済みユーザー
2018/02/26 02:12

回答5件
0
プロパティが public ですと、どんなデータでも直接入れることができます。
これに対して private でアクセサメソッドを経由する場合、特に set する場合において、チェックをすることができます。
つまり、「受け入れることのできるデータだけを確実に通す」ためにアクセサメソッドを使えるのです。
例えばテストの点数であれば、どんなに小さくてもマイナスにはならないはずですし、最高点は100ないし200(TOEIC の900というのもありますが)などになります。
ですからsetするアクセサメソッドは、セットしようとする値が「0~最高点の間」であるかどうかチェックして、変なデータを混入させないようにできるわけです。
また、private なプロパティに対して、「読み取るだけ」のアクセサメソッドを作ることで、データは見せるけど更新はできない、といったこともできます。
投稿2018/02/26 08:38
総合スコア13707
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ゲッターの必要性:データ読み出し時に何らかの処理を行えること。
セッターの必要性:データ書き込み時に何らかの処理を行えること。
特にセッターは意図しない不正なデータの書き込みを許さないよう
与えられたデータの検証を行うために使うことが多いです。
例えば PHP 7.2リリース&PHPのアクセス修飾子、アクセサメソッド、カプセル化、コンストラクタ:Web業界で働くためのPHP入門(14) - @IT の事例では、
本来数字データを格納するべきところに文字列データが来ないように、
さらには数字データとして望ましくない範囲外データを拒否できるように、
セッターで入力データを検証できるようになります。
ゲッターに関しては
例えば読み出された回数を記録できるとか、
デバッグ出力(今読み出されました、を出力)に応用するとか、
そんなところでしょうか。
(実用的に使う場面が、個人的にも今ひとつ思い浮かばない。)
複数人が関わるプロジェクトなどで、
クラスの応用の解釈が揺らがないよう仕様管理していくのでしょうが、
他人が設計・実装したクラスをうっかり間違って使うこともありうるため、
こういう仕組みで防ぐというのもありますし、
ひいてはシステムの脆弱性をついた攻撃に備えることにもつながるかと思われます。
投稿2018/02/26 10:29

退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

退会済みユーザー
2018/02/26 11:32

退会済みユーザー
2018/02/26 12:45
2018/02/26 13:29

0
- PHPにおいては,プロパティに型は指定できない一方,メソッドの引数には**「代入可能な型の制御」** **「代入可能なタイミングの制御」**を課すことができる。この時点でまず
public
ではなくprotected
またはprivate
を採用するメリットがある。 - ファクトリクラス・コンフィグクラス・シングルトンクラス等の一部のユースケースを除き,一般的にオブジェクトはイミュータブルであるほうが望ましいとされるため,Setterはむしろ使わないほうがいい。この考えに則る場合は,プロパティに設定すべき内容はSetterではなくConstructorで渡すようにする。後からプロパティを変更したい場合は,
setXXX
の代わりにwithXXX
という命名を使って,返り値に変更を反映した新しいオブジェクトを返すようにする。 - もしPHPにおいて,プロパティにJavaの
final
(Constructorでのみ代入を認めてそれ以降の変更は認めない)相当の制約を課すことが可能であるなら,public final
で宣言すればGetterは無くても済むが,そのような機能はないため結局のところ多くの場合はGetterが必要になる。また,取得のたびにリアルタイムな値を使って再計算するような場合もGetterが必要。
要するに,protected
なプロパティとGetterをベースにして,Setterはどうしても必要なときだけ使う,が正解です。イミュータブルにしてもコーディングの生産性が落ちない(むしろ分かりやすくなって上がる)場合はイミュータブルを採用しましょう。
(備考)private
と protected
- ライブラリを作る際,高度なユーザによるカスタマイズを認める場合は
private
よりもprotected
のほうが望ましい。また,テストのしやすさを考えてもprotected
のほうが望ましい。本当にprivate
が求められるケースはあまりない。
投稿2018/02/26 18:08
編集2018/02/26 18:12総合スコア5223
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
私もオブジェクト指向はあまり好きではなく、そういった疑問を持っておりました。
結局のところ、業務についてもプロパティと言うものに外部からの値を入れることはあまりなく、
どちらかと言うとそのクラス内で生成した値や、インスタンスなどを格納していることばかりです。
そもそも、同じことを考えている人は多く、「Tell, Don't Ask.」という言葉ができる次第です。
基本getter setterは使わないほうが吉、ということですね。
使うのであれば、本当に必要なのかを再度考え、入れれる値の制約をsetterでかけておくのが良いでしょう。
投稿2018/02/26 08:39
編集2018/02/26 08:40総合スコア2006
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
たとえば日付を表す DateTime クラスなど考えて見てください。
日には普通1から31以外の値を設定できませんが、2月の場合は28または29が最大になります。
ですからsetterではチェックを正確に行うため、年・月・日をまとめてセットする方式が採用されています。
またtime()関数で得られるUNIXタイムスタンプ値を使ってセットすることもできます。
このようにsetter, getter が必ずしもクラスの中のデータと1対1であるとは限らず、必要に応じて複数の出入り口を設けることもあるでしょう。
またいちどnew で生成したら二度と値を再設定できないgetterのみのクラス(Immutableなクラス)もあります。
この要件に応えるため、php5.5でわざわざDateTimeの変更不可なバージョンが登場しています。
http://php.net/manual/ja/class.datetimeimmutable.php
phpが特異なのは、他のJavaやC#などで記述されたアプリと違って、
ユーザからHTTPリクエストを受けてレスポンスを返却すると言う、数秒程度しかデータを保持する期間が無いことです。(ratchetなどは別として)
仮に途中でおかしなデータが混入したとしてもすぐに自然解消します。
タイマーや別スレッドの存在も意識する必要がありません。
このあたりgetterの必然性が感じにくいかもしれませんね。
getterが有意義な例としては、何らかの内部データを返すような処理で、
元データが未定(null)だった時などはExceptionを発生したりWarningを記録させられます。
エラーログを取っていれば読み出し元を知ることができるので、そのような不適切なタイミングでのアクセスを早期発見できます。
またphp7からは関数では public function getDay(): int
のように 戻り値の型を記述できます。
エディタに何を使用しているかわかりませんが、高機能なIDEでは戻り値の型が分かると、
$ret->
など入力すると、続きでメソッドが候補表示され絞り込みもかかります。
書いている途中で人間ではなく機械が型チェックをし、ケアレスミスが防ぐと言うのが最近のプログラミングの流れですから、そう言う書き方に慣れておくことが長期的に見て生産性が上がるのでは無いかと思います。
(この考え方では __get()
、 __set()
などマジックメソッドは、IDEの推測機能を妨害するので避けた方が良いということでもあります)
phpDocでドキュメント化する場合もこの限りではありません。
投稿2018/03/06 09:39
総合スコア97
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。