質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

4回答

1507閲覧

getterがわからない

A2wwM

総合スコア44

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/07/05 06:34

getterとsetterについて勉強しています。

getterは読み専用のため、値の変更はできないはずだと思うのですが
下記のplaygroundで下記のコードを書いてみたところcat.name = "Tamachan"でnameの値を変えているにもかかわらず、エラーが発生しませんでした。

なぜエラーが発生せずに通ってしまうのか教えていただけますと幸いです。

swift

1import UIKit 2 3protocol Animal { 4 // 読み専用 5 var name: String {get} 6 // 読み書き可 7 var age: Int {get set} 8 9 func bark()->String 10} 11 12struct Cat: Animal { 13 var name = "Tama" 14 var age = 2 15 func bark() -> String { 16 return "にゃ〜ん" 17 } 18} 19 20var cat = Cat() 21cat.name 22cat.name = "Tamachan" 23cat.name 24 25cat.age 26cat.age = 3 27cat.age 28cat.bark()

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

それはCat型を使ってnameプロパティにアクセスしているからです。
Cat型のnameはgetもsetも可能な状態です。

一方で、Animalプロトコルを使ってnameに代入しようとした場合ではエラーになります。

イメージ説明

プロトコル(Animal)は「最低限これだけは実装してくださいね」的な情報を定義しているだけで、それを実装している側(Cat)がそれ以上のものを実装してしまってもなんら問題はありません。

投稿2018/07/05 07:10

編集2018/07/05 08:53
takabosoft

総合スコア8356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

A2wwM

2018/07/05 07:54 編集

ありがとうございます。 下でfuzzballさんも似たようなことをおっしゃっていましたね。 ちなみにこのコードは var cat = Cat() var animal = cat as Animal animal.name = "Tamachan" でしょうか? ちなみに、fuzzballさんにも質問してしまったのですが、そうなるとgetter,setterの必要性って何になるのでしょうか?
takabosoft

2018/07/05 08:41

コードはそのような感じでOKです。 Animalプロトコルとしてプロパティのgetだけ必要であれば、getのみの指定で良いです。それを実装する側はたとえばストアドプロパティではなく、コンピューテットプロパティの場合、getのみ書けば準拠できるというメリットがあります(小さなメリットですが)。
takabosoft

2018/07/05 08:42 編集

あとはプロトコルが実際に必要になった時に実感すると思います。
takabosoft

2018/07/05 08:51

「制約」って言葉は適切ではなかったかもしれません。ちょっと変えます。
A2wwM

2018/07/05 09:28

takabosoftさん ありがとうございます。 プロトコルはもうすでに使っていて、便利だなーと少し実感はしていたのですが、理解できないためこれまで意図的にgetter、setterは頭の中から消していました。 もうほかの方にベストアンサーはつけてしまってシステム上takabosoftさんにつけることはできませんが 丁寧に編集までしてくださってありがとうございます。 おかげで理解が深まりました:D
fuzzball

2018/07/05 10:22

ベストアンサーは変更できますよ。
guest

0

Swift

1protocol Animal { 2 // getできることを強制(= 実装クラスでsetできないとは言っていない) 3 var name: String {get} 4 // get、set両方できることを強制 5 var age: Int {get set} 6 7 func bark()->String 8} 9 10struct Cat: Animal { 11 var name : String {get{return "Tama"}} //getだけ実装する 12 var age = 2 13 func bark() -> String { 14 return "にゃ〜ん" 15 } 16} 17 18var cat = Cat() 19cat.name = "Tamachan" // error: cannot assign to property: 'name' is a get-only property 20print(cat.bark())

投稿2018/07/05 08:02

編集2018/07/05 08:11
ozwk

総合スコア13521

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

A2wwM

2018/07/05 10:03

ozwkさん ありがとうございます。 おかげでtakabosoftさんの > Animalプロトコルとしてプロパティのgetだけ必要であれば、getのみの指定で良いです。それを実装する > 側はたとえばストアドプロパティではなく、コンピューテットプロパティの場合、getのみ書けば準拠でき > るというメリットがあります(小さなメリットですが) の理解が深まりました
A2wwM

2018/07/05 10:10

// getできることを強制(= 実装クラスでsetできないとは言っていない) これは実装クラスの方で今回はgetをつかってしまったので不可ですが 自分がしたようにストアドプロパティにすれば値を変更できるからこのように書かれたのでしょうか?
ozwk

2018/07/05 10:22

そうです
guest

0

投稿2018/07/05 07:03

mather

総合スコア6753

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

A2wwM

2018/07/05 07:43

ありがとうございます これ自分もみたのですが理解できなくて。。
mather

2018/07/05 08:07

例えばJavaでもインターフェースにはgetterしか定義されていなくても、それを実装する具象クラスでsetterを定義することには何も問題がありません。 あくまでも「Animalプロトコルとして」オブジェクトと接するときの制約(ルール)だと思います。
guest

0

ベストアンサー

Animalとしてアクセスするときはread-onlyだけど、
Catとしてアクセスするときは(var nameだから)書き込みできる。

なんてのは、どうでしょうか?

swift

1(cat as Animal).name = "hoge" 2//=> Cannot assign to property: 'name' is a get-only property

ちなみに、let age = 2にすると、setを満たしていないのでエラーになる。

swift

1//=> Type 'Cat' does not conform to protocol 'Animal'

投稿2018/07/05 07:04

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

A2wwM

2018/07/05 07:44 編集

ありがとうございます 上でtakabosoftさんもおっしゃっていますが、プロトコルを採用してもその属性まで制約として採用されな いということなんでしょうか。 だからvarにしたら変更できるし、letにしていたら変更できない。 ちなみにそうなるとgetterとかsetterの必要性があまり見えないですね。
mather

2018/07/05 07:48

例えば関数の返り値が Animal で定義されていれば、返り値については変更不可になるのですから有効ではないですか?
A2wwM

2018/07/05 08:00

なるほど。 ちょっとこれに関しては調べてみたら他でも議論されているようなのでそれも見てみます。 matherさんありがとうございます。 とりあえず本件は終了します
fuzzball

2018/07/05 08:00

>>プロトコルを採用してもその属性まで制約として採用されないということなんでしょうか。 いや、されてますよ。(回答の後半がその例) >>getterとかsetterの必要性があまり見えないですね そういう用途に使うものでは無いということです。
fuzzball

2018/07/05 08:06

「制約」の解釈の仕方かと。 「getしかできないString型のnameが必要」なのではなく「getできるString型のnameが必要」ということですね。
A2wwM

2018/07/05 10:11

>>>> プロトコルを採用してもその属性まで制約として採用されないということなんでしょうか。 >> いや、されてますよ。(回答の後半がその例) ほんとだ。get setなのに、letにしたんで、エラー起こしてますね ということは、nameをコンピューテッドプロパティにしていれば、これはよかった(= エラーが出る)ということでしょうか
fuzzball

2018/07/05 23:49

letじゃダメなんでしょうか?
A2wwM

2018/07/06 01:32

letだと値変更できないのでだめなのかと思いましたが
fuzzball

2018/07/06 01:49

値は変更できるけど cat.name = "Tamachan" でエラーを出したいのでしょうか?
A2wwM

2018/07/06 01:59

分かりづらくてすみません。cat.name = "Tamachan"でエラーを出したかっただけです。 今回はgetter setterの勉強をしていて、自分の理解が正しいのか確認するためにplaygroundを使って確認してみました。 その際に冒頭で書いたコードで期待結果としてエラーがでると思ったのですが、実際の結果は異なっていたので確認したくて質問しました
fuzzball

2018/07/06 02:11

それならletでいいのでは‥。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問