32113


[![画像の説明をここに入力](https://i.stack.imgur.com/DLEqe.png)](https://i.stack.imgur.com/DLEqe.png)swift初心者です。クラスの継承をしようとするとタイトルのように怒られます  
loadSCVクラスからnumberプロパティとdata配列を  
step1クラスで使用したいのですが  
numberは使用することができましたが、data配列は宣言エラーが出て使用できないです  
ご指摘お願いします。  
コードは以下の通りです

[code]

    class loadCSV {
        let number = 32
        func loadCSV(){
            var data = [[String]](repeating: [String](repeating: "", count: number), count: number)
    
            if let csvUrl = Bundle.main.url(forResource: "data0112", withExtension: "csv") {
                do {
                    let csvData = try String(contentsOf: csvUrl)
                    let dataList = csvData.components(separatedBy: ",")
                    if dataList.count > number * number {
                        print("error")
                        return
                    }
                    for (n, item) in dataList.enumerated() {
                        data[n / number][n % number] = item
                        print(data[n / number][n % number])
                    }
                } catch {
                    fatalError("Not found CSV files")
                }
            }
        }
    }
    
[/code]

[code]

    class step1 : loadCSV{
        func step1(){
            var d = [[String]](repeating: [String](repeating: "", count: number), count: number)
            d = data
            let a : Double = 900.0
            let b : String = String(a)
            for i in 0...d.count{
                for j in 0...d.count{
                    if d[i][j] == "0.0"{
                        d[i][j] = b
                    }
                }
            }
        }
    }
    
[/code]


CC BY-SA 3.0
2017-01-24T05:55:56.013
32105
2017-01-25T15:17:07.597
2017-01-24T06:35:11.907
19110
19087
question
swift3
クラス継承でエラー　property does not override any property from its superclass


data配列は、親クラスの関数 loadCSV の中の変数であって、親クラスのプロパティではありません。  
そのため、親クラスを継承しても参照することが出来ないのです。


CC BY-SA 3.0
2017-01-24T09:20:24.833
32111
2017-01-24T09:20:24.833
217
32105
answer


### クラスの基本形

クラス定義の基本形を示します。

[code]

    class クラス名 : スーパークラス名, 【準拠するプロトコル名】 { // カッコ内はオプション
        var プロパティ名: 型名 【= 初期値】
        func 【インスタンス】メソッド名(引数名: 型, ・・・) 【-> 返り値の型】 {}
    }
    
[/code]

クラスの基本構成物は、ほかにイニシアライザ、定数、クラスメソッド、タイププロパティ、タイプメソッドなどありますが、必要十分条件の必要条件は、プロパティと（インスタンス）メソッドです。ご提示のコード中のクラス`loadCSV`と`step1`いずれにも、プロパティがなく、それでコンパイルエラーになりませんが、クラスとは何か、何を目的にしているのかという、そもそも論を考えると、何も値を保持しないクラスは、蜜や花粉を巣に持ち帰らないミツバチと同じといえます。  
※ここでいう **プロパティProperty** は、 **インスタンス変数Instance Variable**
と呼ぶことがあります。オブジェクト指向言語の多くで、インスタンス変数という用語が使われているので、そちらの方が通りがいいのですが、厳密には、プロパティとインスタンス変数は同じではないので、プロパティを使います。

* * *

### 変数のスコープ（有効範囲）

変数には有効範囲があり、有効範囲をスコープと呼びます。そして基本として、ブロック（{から}で囲まれた、コードの集まり）がすなわちスコープになります。変数のスコープは、変数の寿命といってもよくて、プログラムの実行がブロックから抜けると、ブロック内の変数は解放されます。

[code]

    func hoge() {
        var a: Int
        a = 200
        do {
            var a: Int
            a = 100
            print("Local a = \(a)")
        }
        print("Global a = \(a)")
    }
    
    hoge()
    
    // "Local a = 100"
    // "Global a = 200"
    
[/code]

Playgroundで上のコードを書いて、実行してみてください。  
ブロックは、関数（メソッド）、条件文、繰り返し文などで使われますが、独立したブロックを作ることもでき、その場合、Swiftでは、`do`を頭につけます。  
関数`hoge`内で、変数`a`を重複して宣言していますが、コンパイルエラーにも、実行エラーにもなりません。それは、ブロックが入れ子になっており、`do
{}`内の変数`a`の有効範囲がブロック内に限定されるからです。

[code]

    func hoge() {
        do {
            let b = 300
        }
        print("b = \(b)") // Use of unresolved identifier 'b'
    }
    
    hoge()
    
[/code]

ブロックの外で、変数`b`にアクセスしようとすると、「変数が定義されてない」とエラーになります。

ここまでで、クラス`step1`のメソッド`step1()`で、`d = data`の行でエラーになる理由がお分かりになりましたでしょうか？  
変数をクラス内のどこでも使えるようにするには、プロパティとして宣言することです。プロパティとして宣言するということは、同時に、変数の寿命が、インスタンスの寿命と同じになることも意味します。（インスタンス外部からアクセスできる点もあり、大事ですが、ここではその説明は割愛します）

* * *

以下、ご提示のコードに改良を加えたコードを載せます。メソッド`loadCSV()`の実装を、イニシアライザに移動しています。この変更が、プログラム全体の設計の中で、妥当なものかは、私には判断できません。  
それと、配列dataの要素の型を、`String`から`Double`に変更しています。これもご提示のコードの範囲だけで判断すれば、要素を文字列でなく数値にすべきだからです。プログラム全体の設計から判断したものではありません。

[code]

    import UIKit
    // import Foundation // UIKitがFoundationをインポートしているので、不要。
    
    class LoadCSV { // 型名（クラス名含む）は、大文字で始めるという規則があります。
        let number = 32
    
        var data: [[Double]] // プロパティとして、dataを宣言。
    
        // イニシアライザ
        init() {
            data = [[Double]](repeating: [Double](repeating: 0.0, count: number), count: number)
    
            if let csvUrl = Bundle.main.url(forResource: "data0112", withExtension: "csv") {
                do {
                    let csvData = try String(contentsOf: csvUrl)
                    var dataList = csvData.components(separatedBy: ",")
                    let listCount = dataList.count
                    // dataListの要素数が、number * numberを超えた場合、number * numberを残して、はみ出した分は切り捨てる。「エラーと出力して終わり」ではさすがにまずいでしょう。
                    if listCount > number * number {
                        dataList = [String](dataList[0..<number * number])
                    }
                    for (n, item) in dataList.enumerated() {
                        if let theNumber = Double(item) {
                            data[n / number][n % number] = theNumber
                        } else {
                            data[n / number][n % number] = 0.0
                        }
                    }
                } catch {
                    fatalError("Not found CSV files")
                }
            }
        }
    }
    
    class Step1 : LoadCSV{ // 型名（クラス名）を大文字で始める。
        func step1(){
            let a: Double = 900.0
    
            for row in 0..<data.count { // 後述
                for i in 0..<data[row].count {
                    if data[row][i] == 0.0 {
                        data[row][i] = a
                    }
                }
            }
    
    // mapメソッドを使った場合。
    //        data = data.map{ row in
    //            row.map{ item in
    //                if item == 0.0 {
    //                    return a
    //                } else {
    //                    return item
    //                }
    //            }
    //        }
        }
    }
    
    let obj = Step1()
    obj.step1()
    print(obj.data)
    
[/code]

* * *

`Range`（範囲）の書き方の誤解があるので、質問と直接関係ありませんが、説明しておきます。  
`Range`には、[CountableRange](https://developer.apple.com/reference/swift/countablerange)と[CountableClosedRange](https://developer.apple.com/reference/swift/countableclosedrange)があります。  
`0..<32`は、`0 ≦ x < 32`で、`0...32`は、`0 ≦ x ≦ 32`です。使用を間違うと、out of
rangeのエラーになります。


CC BY-SA 3.0
2017-01-24T10:53:34.303
32113
2017-01-25T15:17:07.597
2017-01-25T15:17:07.597
18540
18540
32105
answer