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

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

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

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

Q&A

解決済

1回答

1082閲覧

サブクラスでsuper.init()とoverrideメソッドの記載方法

pegy

総合スコア243

Swift

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

0グッド

0クリップ

投稿2020/11/02 03:44

a swift tourを読みながらサブクラスの作り方について勉強をしていました。
下記の様なサブクラスを作ることにあまり意味はないのですが、倣って作成してみたのですが、諸々エラーが発生し動作してくれません。

tourには具体的な説明がなくいきなりsuper.init()が使用されているのですが、superクラスのプロパティをサブクラスから初期化される場合にサブクラス側のイニシャライザーでこの様に書くものと解釈しています。
overrideはスーパークラスから関数を書き換える場合にこの様に書くものと解釈しています。

どこに問題点があるのか、アドバイスをいただけるとありがたいです。
よろしくお願い申し上げます。

swift

1class vehicle { 2 var wheel:Int 3 var name:String 4 init(name: String, wheel: Int) { 5 self.name = name 6 self.wheel = wheel 7 } 8 func announce()-> String{ 9 return "this is (name) with (wheel) wheel(s)" 10 } 11} 12 13var car = vehicle(name: "car", wheel: 4) 14print(car.announce()) 15 16var creature: vehicle { 17 var legs: Int 18 init(legs: Int, name: String){//Initializers may only be declared within a type 19 self.legs = legs 20 super.init(name:name)//'super' cannot be used outside of class members 21 } 22 override func announce()-> String{ //'override' can only be specified on class members 23 return "this is (name) with (legs) legs" 24 } 25} 26 27var human = creature(name: "human", legs: 2) 28print(human.announce())

a swift tourのコード

swift

1class NamedShape { 2 var numberOfSides: Int = 0 3 var name: String 4 5 init(name: String) { 6 self.name = name 7 } 8 9 func simpleDescription() -> String { 10 return "A shape with (numberOfSides) sides." 11 } 12} 13 14class EquilateralTriangle: NamedShape { 15 var sideLength: Double = 0.0 16 17 init(sideLength: Double, name: String) { 18 self.sideLength = sideLength 19 super.init(name: name) 20 numberOfSides = 3 21 } 22 23 var perimeter: Double { 24 get { 25 return 3.0 * sideLength 26 } 27 set { 28 sideLength = newValue / 3.0 29 } 30 } 31 32 override func simpleDescription() -> String { 33 return "An equilateral triangle with sides of length (sideLength)." 34 } 35}

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

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

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

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

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

guest

回答1

0

ベストアンサー

コンパイルが通らない理由はエラーメッセージの通りで、「type(= class, struct, enum)でないものに対してイニシャライザを宣言している」ことがその理由です。

Swift

1// イニシャライザはクラスや構造体(つまり、type として宣言できるもの)にしか宣言できない 2//var creature: vehicle { 3class creature: vehicle { 4 var legs: Int 5 init(legs: Int, name: String){ 6 //Initializers may only be declared within a type 7 // 変数(var)に対してイニシャライザを宣言したので上記のエラーが出ていた 8 self.legs = legs 9 //super.init(name:name)//'super' cannot be used outside of class members 10 // 上記と同様。ちなみにsuper.init() と引数の数があっていないので合わせる必要がある 11 super.init(name: name, wheel: 0) 12 } 13 override func announce()-> String{ //'override' can only be specified on class members 14 return "this is (name) with (legs) legs" 15 } 16} 17 18//var human = creature(name: "human", legs: 2) 19// イニシャライザの引数の順番が間違っている 20var human = creature(legs: 2, name: "human") 21print(human.announce())

投稿2020/11/02 04:34

TsukubaDepot

総合スコア5086

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

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

pegy

2020/11/02 04:57

的確なご指摘をいただきありがとうございます。 var creature: vehicle については大変失礼いたしました。根本的すぎて、見落としてしまいました。。 さて、一点だけ少し疑問が残るのですが、 //super.init(name:name)//'super' cannot be used outside of class members // 上記と同様。ちなみにsuper.init() と引数の数があっていないので合わせる必要がある super.init(name: name, wheel: 0) のご指摘についてです、super.init()はスーパークラスのプロパティを継承して初期化する場合に利用されるという認識なのですが(本文記載の通り、断りなく利用されているので不完全な認識で申し訳ございません)その上で、 ”引数の数があっていないので合わせる必要がある というのはどの引数の数に合っておらず、どれに合わせるということなのでしょうか? 文脈的にスーパークラスvehicleのプロパティで初期化していないものの数に合っていないので、これに合わせる必要があるということかと思うのですが、合っていますでしょうか? であるとすれば、a swift tourの例ではスーパークラスがわでvar numberOfSides: Int = 0の様に初期化しているので、サブクラスでは初期化不要?なのかと解釈されますが。 super.init()とは、superクラスで初期化していないものを全て初期化するためにサブクラス側で初期化されるもの と言い換えて捉えても差し支えないのでしょうか? 重ねて申し訳ございませんが、よろしくお願い申し上げます。
TsukubaDepot

2020/11/02 06:10

creature が vehicle を継承しているのであれば、基底クラス(継承元)のイニシャライザは class vehicle { init(name: String, wheel: Int) {} } になります。ここで指定している通り、引数は2つ必要で、また規定値は定義されていないので、2つの引数はいずれも値の指定が必要です。 一方、継承先では class EquilateralTriangle: NamedShape { init(sideLength: Double, name: String) { super.init(name: name) と、基底クラス(スーパークラス)の呼び出し、つまり super.init の引数が1つしか指定されていません。 基底クラスでイニシャライザを複数宣言し、そのうちのいずれかと合うのであればこれで問題ありませんが、基底クラスにはイニシャライザは一つしかありませんので、このままでは適切なイニシャライザを見るけることができず、コンパイルエラーとなってしまいます。 これはイニシャライザに限らず、通常のメソッドでも同じです。オーバーロード(書き換えである「オーバーライド」とは違います)とほぼ同じ考え方です(ほぼ、というのはイニシャライザの動作が構造体とクラスでは異なるためです)。
TsukubaDepot

2020/11/02 06:35

> であるとすれば、a swift tourの例ではスーパークラスがわでvar numberOfSides: Int = 0の様に初期化しているので、サブクラスでは初期化不要?なのかと解釈されますが。 一方、作成されているコードでは var wheel:Int var name:String の2つの値がありますが、これらはイニシャライザが作動する前には初期化されていません。 したがって、イニシャライザ内でなんらかの値を代入するか、イニシャライザがとった引数で初期化する必要があります。 いずれにしても、それがイニシャライザであれメソッドであれ、引数の順番と型は合わせるのが大原則です。
pegy

2020/11/02 06:50

ご回答をいただきありがとうございます。 ①スーパークラスのいずれかのイニシャライザとサブクラスのそれを合致させる(規定値が定義されていない場合) ②インスタンス化する場合、引数の順番と型を合わせる この2点について、承知をいたしました。 勉強になりました、よろしくお願い申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問