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

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

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

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

Q&A

解決済

3回答

1881閲覧

swift言語のインスタンスとイニシャライザ

vlb

総合スコア109

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

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

1グッド

0クリップ

投稿2019/01/05 06:26

編集2019/01/22 23:37

swift言語のインスタンスとイニシャライザ

swiftではクラスのインスタンスを生成する際は引数を渡すことでイニシャライザを呼び出す必要があると認識しています.

そこで質問です.

1つ目のコードの20行目のvar cymbalPlayer = AVAudioPlayer()AVAudioPlayerのインスタンを生成していますが,なぜ引数を渡すことなくインスタンを生成できるのでしょうか.

私は2つ目のコードのように書く必要があると思うのですが,これだと音が一瞬しかな流れないということはわかります.

引数なしのイニシャライザであれば引数を渡さずにインスタンスを生成しますが,引数ありのイニシャライザを保有しているクラスのインスタンスを生成するときはイニシャライザのための引数を渡す必要がありますよね?

swift

1import UIKit 2import AVFoundation 3 4class ViewController: UIViewController { 5 6 override func viewDidLoad() { 7 super.viewDidLoad() 8 } 9 10 override func didReceiveMemoryWarning() { 11 super.didReceiveMemoryWarning() 12 } 13 14 let cymbalPath = Bundle.main.bundleURL.appendingPathComponent("cymbal.mp3") 15 16 var cymbalPlayer = AVAudioPlayer() 17 18 @IBAction func cymbal(_ sender: Any) { 19 do { 20 cymbalPlayer = try AVAudioPlayer(contentsOf: cymbalPath, fileTypeHint: nil) 21 22 cymbalPlayer.play() 23 } catch { 24 print("シンバルで、エラーが発生しました") 25 } 26 } 27}

swift

1import UIKit 2import AVFoundation 3 4class ViewController: UIViewController { 5 6 override func viewDidLoad() { 7 super.viewDidLoad() 8 } 9 10 override func didReceiveMemoryWarning() { 11 super.didReceiveMemoryWarning() 12 } 13 14 let cymbalPath = Bundle.main.bundleURL.appendingPathComponent("cymbal.mp3") 15 16 @IBAction func cymbal(_ sender: Any) { 17 do { 18 var cymbalPlayer = try AVAudioPlayer(contentsOf: cymbalPath, fileTypeHint: nil) 19 20 cymbalPlayer.play() 21 } catch { 22 print("シンバルで、エラーが発生しました") 23 } 24 } 25}

追加

引数なしのインスタンスを生成した後に,引数ありのインスタンスを代入するという観点からみれば下のコードのような意味不明なコードになると思うのですが,なぜAVAudioPlayerは許されるのでしょうか.

swift

1class A { 2 init(string: String){ 3 } 4} 5 6var a = A() 7a = A(string: "~~~")

環境
xcode:10
swift:4.2

言葉足らずでしたらご指摘ください.

dja👍を押しています

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

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

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

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

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

fuzzball

2019/01/21 00:47

すでに正しい回答がついているのに、なぜ回答を求めているのでしょうか?
AOKINAO

2019/01/21 01:26

「引数があるもの”だけ”をイニシャライザと呼ぶ」と勘違いしているのでは? 引数のないイニシャライザもありますよ。
fuzzball

2019/01/21 08:56

>>2つ目のコードの方が正しい書き方だと思うのですが,間違っているようです. なぜ間違っていると思ったのか書いて下さい。
vlb

2019/01/22 23:40

>>AOKINAOさん 引数がないイニシャライザがあることは知っていますが,AVAudioPlayerは引数があるイニシャライザを宣言していますよね?
guest

回答3

0

ベストアンサー

1つ目のコードの20行目のvar cymbalPlayer = AVAudioPlayer()はAVAudioPlayerのインスタンを生成していますが,なぜイニシャライザを呼び出すことなくインスタンを生成できるのでしょうか.

AVAudioPlayer()は、AVAudioPlayerの init()を呼び出しています。
実際には init()はAVAudioPlayerの継承元クラスである NSObject
定義したものが継承されていて、基本的な初期化が行われるだけで、
音源を指定して初期化していないため、これを使って実際に音を鳴らすことは
おそらくできないと思います。
(後から音源をセットできるなら話は別ですが、おそらくできなかったと思います。)

つまり、var cymbalPlayer = AVAudioPlayer()AVAudioPlayer()は、
cymbalPlayerの初期値を仮設定するために生成したインタンスで、
後で実際に使用する時に、正しく音源を指定して初期化したAVAudioPlayerインスタンスを
代入してから使用するものと考えればいいです。

私は2つ目のコードの方が正しい書き方だと思うのですが,間違っているようです.
なぜでしょうか.

これは、 do { 〜 }のブロックの中でcymbalPlayer変数を新しく宣言しており、
このdoブロックを抜けると、cymbalPlayer変数は消滅し、その中に入っていた
AVAudioPlayerインスタンスも消滅してしまうためです。
ViewControllerが存在している間音を鳴らしつづけたい場合は、
ViewControllerのプロパティとしてAVAudioPlayerの変数を宣言し、
ViewControllerが存在している間、AVAudioPlayerインスタンスが消滅しないように
する必要があります。

投稿2019/01/05 15:21

TakeOne

総合スコア6299

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

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

vlb

2019/01/21 14:44 編集

回答ありがとうございます. ////////////////////////////// class A { init() { } } class B: A { init(string: String) { } } var b = B() b = B(string: "~~~") ////////////////////////////// このコードは明らかに間違っていると思うのですが,クラスBのインスタンス生成時に,継承元のクラスAのinit()呼び出そうとしている,という点ではAVAudioPlayer()の例と同じように見えるのですが,私が書いたコードとAVAudioPlayer()ではどのような部分で違いがあるのでしょうか.
fuzzball

2019/01/21 09:12

AVAudioPlayer()の実装が分からないのに、こんな比較をしても無意味ですが、 エラーを出なくするだけなら、クラスBでinit()をoverrideして下さい。
TakeOne

2019/01/22 14:54

おそらくAVAudioPlayerは実際にはObjective-Cで書かれていて、それをSwiftから使えるようにしていると思います。似たような構成をSwiftで定義するなら、init()をoverrideする必要があります。「どのような部分で違いがあるのでしょうか」と聞かれたら、たぶん実装している言語から違います。ただ、fuzzballさんも指摘している通り、実際にどのように実装しているかはAppleから公開されていませんから、Swiftのコードと比較しても無意味だと思います。
vlb

2019/01/23 09:13

>>fuzzballさん クラスBでinit()をoverrideすると,どのようなコードになりますか?
fuzzball

2019/01/23 09:14

override init() {}
vlb

2019/01/23 09:20

ではなぜAVAudioPlayerクラスにはoverride init() {}が宣言されていないのに,引数なしのインスタンスを生成できるのでしょうか.
fuzzball

2019/01/24 01:23 編集

>>なぜAVAudioPlayerクラスにはoverride init() {}が宣言されていないのに これはソースコードを見ないと分からないのでは? (まぁ、AVAudioPlayerはObjective-Cで書かれているそうなので、もしそうならoverride云々は関係ないですが) NSObjectのGenerated Interfaceには、 public init() と書かれていますので、継承したクラス(AVAudioPlayer)からも呼べる(見える)のではないかと思います。
guest

0

TakeOneさんのコメントにも少しありましたが,

Objective-Cで書かれていて継承ツリーの中にinit()があれば使えます。そう決まってます。 NSObjectにinit()があるのでNSObjectを継承していたら init() が使えます。

とのことでした.
回答してくださった皆様,ありがとうございました.

投稿2019/01/23 14:12

編集2019/01/23 14:14
vlb

総合スコア109

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

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

0

追記の質問に対して。

swift

1var cymbalPlayer = AVAudioPlayer()

としているのは、cymbalPlayerをオプショナル型にしなくないからだと思います。
(理由はおそらく、後で使うときに面倒臭いからではないかと)

きちんとしたいならcymbalPlayerをオプショナル型にして下さい。
そうすれば、意味のないインスタンスを生成しなくて済みます。

投稿2019/01/22 00:21

fuzzball

総合スコア16731

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問