全ての言語に共通することかもしれませんが、今Swiftの構造体やクラスを勉強していますがイニシャライザを定義することで初期化する意味がまだピンときません。
こちらの投稿でイニシャライザが存在する理由は読み解くことができたのですが、そもそもなぜ値型の構造体や参照型のクラス初期化をしなくてはいけないケースが出てくるのでしょうか?
例えばこの様なqiitaの投稿でcard構造体を定義していますがイニシャライザは定義されていませんが、特に不便がない様に思えます。
なぜ、そもそも初期化をするのか、初期化しなければどの様な不便が起きるのかという観点からご教示いただけますでしょうか?
よろしくお願い申し上げます。
逆に、初期化しない場合の問題点を考えてみてはいかがでしょうか。
初期化しないでアクセスした場合、どのような値が出てくると想像できますでしょうか。
構造体(値型)であれ、クラスで(参照型)あれインスタンスを生成する際に
let yobidashi = kozotaidesu(Int:10, Int: 20)
let yobidashi = classdesu(Int:10, Int: 20)
インスタンス側のプロパティだけに10や20が格納されるので、構造体やクラスそのものの値には影響がない様な直感があります。
class classdesu {
let classprop: Int =10;
//他の処理
}
print(classdesu.classprop)
の様に引数で値をとらない場合、そもそもクラスや構造体側でプロパティ値を指定していて、それを固定して利用したいため、初期化も何も常に値は固定であるという感覚を持っています。
これらの解釈自体がずれていたら誠に申し訳ございません。
「インスタンス側のプロパティだけに10や20が格納されるので、構造体やクラスそのものの値には影響がない」という解釈がイメージできないのですが、たとえばどのような状況を考えていらっしゃるのでしょうか。
クラスは設計図でインスタンスはクラスを実体化したものと認識しております。
したがって、
let yobidashi = classdesu(Int:10, Int: 20)
においては、設計図であるclassdesuは10や20というプロパティは知らず、実体側であるyobidashiインスタンスがそのプロパティとして10や20を知っているというイメージです。
よろしくお願い申し上げます
「設計図であるclassdesuは10や20というプロパティは知ら」ないので(正確には「個々のプロパティに代入する値を知ら」ない)、「実体側であるyobidashiインスタンス」を作るときに「10や20という値で初期化」しなければいけないのはご理解いただいていると思います。
しかし、そうなるとご質問の意図である「初期化をする理由がわかりません」が理解し難いのですが、どこに悩まれているのでしょうか。
>「実体側であるyobidashiインスタンス」を作るときに「10や20という値で初期化」しなければいけないのはご理解いただいていると思います。
ここがおそらく理解できておりません。
例えば変数に値を格納する場合、
let hoge:string = "1st"
で終わる作業で、ここで何かを初期化するという概念はない(それとも私が気付いていない)と思います。
そこで例えば、以下の記事に
https://www.sejuku.net/blog/34191
class SampleClass {
//変数の定義
var num = 0
var str1 = ""
var str2 = ""
//イニシャライザ
// init(){
// self.num = 100
// self.str1 = "Samurai"
// self.str2 = "Engineer"
// }
}
let inst = SampleClass();
print(inst.num)
で問題なく0が出力されます
一方で
class SampleClass {
//変数の定義
var num = 100
var str1 = ""
var str2 = ""
//イニシャライザ
// init(){
// self.num = 100
// self.str1 = "Samurai"
// self.str2 = "Engineer"
// }
}
let inst = SampleClass();
print(inst.num)
でも同じ様に100が出力されます。
ではなぜinit(){}が必要であるのか?というところが疑問でございます。
> ではなぜinit(){}が必要であるのか?というところが疑問でございます。
端的に言えば、「宣言時にすべてのプロパティが初期化(何らかの値が代入)されているのでイニシャライザ(あえて日本語化すれば「初期化子」)が必要ない、ということです。
逆に、何らかの値を一つでも代入していないクラスはイニシャライザが必須です。構造体は多少振る舞いが異なり、自分でイニシャライザを書く必要はないのですが、インスタンスを生成するときには初期化されていない変数についてすべて初期化を行う必要があります。
いま手元に資料がないのでより正確なことは言えないのですが、以前お勧めした下記の書籍
>(参考文献)
>詳解 Swift 第5版
>著者 萩原剛志
>発行者 SBクリエイティブジャブ式会社
には、構造体、クラスに関するイニシャライザの解説が詳しく載っていると思いますので、まずはそれを読み直されてはいかがでしょうか。
例として提示されたリンクの内容はかなり怪しいので(著者が説明できない部分をあえて濁している感じがあるので)参考にしない方がいいかと思います。
いま改めて参考にされたリンクを見ましたが、やはり例示がおかしいというか、イニシャライザの意味が感じられない例しか出していないようです。
イニシャライザで決まった値を代入することはできますが、それだとイニシャライザのメリットがありません。イニシャライザのメリットの一つは、インスタンスを生成するときに、プロパティの値を動的に決めることができる点があるかと思います。
たとえば、
let a = Int(2)
とすれば、Int 型で初期値が「2」のインスタンスが生成されますし、
let a = Int(3)
とすれば、Int 型で初期値が「3」のインスタンスが生成されます。
もし、このように動的に値を決めることができない(初期化できなければ)
var a = Int()
a = 3
と後から値を代入しなおす(初期化しなおす)処理が必要になり、煩雑になってしまいます。
また、インスタンスを初期するにあたって「最低限指定しなければいけない値」が分かっていなければ(つまり、イニシャライザの引数として指定されていなければ)、インスタンスを生成後、自分でどのプロパティに値を代入しなければならないのかも把握することができません。
さらには、初期化しなければ使いことができないメソッドを、あるプロパティの初期化前に呼び出してしまうとその時点でエラーとなってしまいます。こうなってしまうと、もはやどこに根本的なエラーがあるのか把握することすら困難になってしまいます。
覚えてくださっていて、ありがとうございます。まさに参考文献の構造体の箇所にイニシャライザを読んでいて、道に迷ってしまいました。読み込みがまだまだ足りないのかもしれません。
初期化というのは代入を値するという読み替えることができるのですね、。
以下の様にプロパティを値を動的に決めることができるのが直感的に理解できました。もちろん、これはそれだけでは意味がなく、ここで動的に指定したプロパティをインスタンスメソッド等で利用したりすることで意味があることなのかもしれません。
class Bar {
var a: UInt8
init(a: UInt8) { self.a = a}
}
let inst = Bar(a:100);
print(inst.a)
一方で
>何らかの値を一つでも代入していないクラスはイニシャライザが必須です。構造体は多少振る舞いが異なり、自分でイニシャライザを書く必要はないのですが、インスタンスを生成するときには初期化されていない変数についてすべて初期化を行う必要があります。
については、なぜそうなのかというのが直感的にはわからないのですが、(確かに値も代入していないクラスのプロパティを定義すること自体が意味がないのですが)(コンパイル上の理由?)これは引き続き調べてみようと思います。
ありがとうございます。
イニシャライザの振る舞いは結構複雑(のように感じる)ので、最初から全てを理解するのも大変かと思います。
よく使う ViewController もクラスなのですが、そこには明示的なイニシャライザがないので、イニシャライザの必要性も感じられないのも誤解の理由かもしれません(イニシャライザがない代わりに、初期値が代入されていないプロパティがあるとコンパイルエラーになる)。
この辺りはいろいろ試されてみて、実感されるのが一番いいのではないでしょうか。
とりあえず、一旦落ち着きそうであれば、自己解決のような形で質問を閉じていただいてもよろしいでしょうか。
お手数をおかけしますが、よろしくお願いします。
初心者のわかりづらい質問にお付き合いをいただき誠にありがとうございます。
本当に心から感謝を申し上げます。
よろしくお願い申し上げます。
回答1件
あなたの回答
tips
プレビュー