【Swift vs Java】staticとfinalをいい加減理解しよう

## Static

staticのClassのメンバーで、変数、メソッド、ブロック、ネストクラスにつけることができる。(だいたいvariableとmethod)

staticキーワードをつけると、**インスタンスなしでクラスの中にあるstaticメンバーにアクセスできる**。また、インスタンスをいくら作っても全てのインスタンスで同じ値やメソッドが共有されます。

'static'なメソッドはインスタンスに属していないため、インスタンスのメンバーにアクセスできない。'static'なメンバーは'static'メソッドからしかアクセスできない。

### どういう時に使うの？
 
クラスが作成されてようが、されてまいが関係ない時にstaticを使う。例えば、Student（学生）クラスの中に、名前と学校名の変数があったとしたら、
名前はユニークなので、instance variableで学校名はその生徒がいなくても独立しているのでstatic variableです。
メソッドも同じで、生徒と関係ないメソッドはstaticにしておく感じ。

何が便利って、**クラスの中のstaticを変更すると、クラスを参照している全てのオブジェクトのstatic値が変わること！**




### Java

```Main.java
public static void main(String args[]){
     Student s1 = new Student("Yagami");
     Student s2 = new Student("Dekisugi");

     s1.display();
     s2.display();

     System.out.println(Student.collegeName);
}
```

```Student.java
public class Student {

        String name;
        static String collegeName ="Tokyo University";

        Student(String newStudentName){
            name = newStudentName;
        }
        void display (){
            System.out.println(name+" "+collegeName);
        }
}
```

### Swift

```Main.swift
let s1 = Student("Yagami")
let s2 = Student("Dekisugi")

s1.display()
s2.display()

print(Student.collegeName)
```

```Student.swift
public class Student {
    
    var name:String?
    static var collegeName:String?
    
    init(_ name:String) {
        self.name = name
    }
    
    func display() {
        print("\(name) \(Student.collegeName)")
    }
}
```

**ポイント1**
 JavaのSwiftもだいたい同じですが、
唯一の違いが、static変数のアクセス方法です。

 - Swiftではクラス内にいようがいまいが、staticメンバーをアクセスするのに、
`Student.collegeName`と、クラス名を冒頭につける

 - Javaではクラス内にいるときは、冒頭にクラス名をつけなくてもよい

**ポイント２**
上記を見ると、設定していないのに二人の生徒の学校名が"Tokyo University"になっている。そして、staticな変数はもクラスに参照されないため、コンストラクターでも使われない！

## クラス内でのstatic変数とstaticメソッドのアクセス権

### Java


```Prorammer.java

public class Programmer {

    private static boolean isGood;
    private int experienceYears;

    public static void main(){

        // StaticなメソッドからはStatic変数をアクセスできる
        isGood = true;

        //＊Staticなメソッドからnon-Static変数はアクセスできない。参照を使わないとだめ
        Programmer person1 = new Programmer();
        person1.experienceYears = 10;
    }

    // non-staticなメソッドからstatic変数はアクセスできる
    public void setExperienceYears(int years){
        this.experienceYears = experienceYears;
    }

    // non-staticなメソッドからnon-static変数はアクセスできる
    public void setIsGood(Boolean isGood){
        isGood = isGood;
    }
}
```

### Swift

```.swift
class Programmer{
    
    static var isGood:Bool?
    var experienceYears:Int?
    
    
    static func execute(){
        isGood = true
        
        //static メソッドからはnon-static変数はアクセスできない。インスタンスが必要
        let person1 = Programmer();
        person1.experienceYears = 10;
        
    }
    
    //non-staticなメソッドからはアクセスできる
    func setExperience(_ years:Int){
        self.experienceYears = years
    }
    
    //non-staticなメソッドからはstatic変数を直接アクセスできない。クラス名が必要。
    func setIsGood(_ isGood:Bool){
        Programmer.isGood = isGood
    }
}
```


## Final

Finalをつけた時のそれぞれの特徴。変数の意味だけが変わる
### Java

| Final Class | Final Variable | Final Method |
|-------------|----------------|--------------|
| no child    | constant       | no override  |


### Swift

| Final Class | Final Variable          | Final Method |
|-------------|-------------------------|--------------|
| no child    | no override in subclass | no override  |


### Final Class

**Java**

```.java
//これはOkだけど
final public class Final extends Queen { }

//これはNG = compileエラー
public class King extends Final { }

```

**Swift**

```.swift
//OK
final class Final: Programmer { }

//NG　= compileエラー
final class Student: Final { }

```

### Final Variable

**Java**
Constantになるので値が変えられなくなる。Swiftでいうletですね。

**Swift**

```.swift
//OK クラス内ではfinal変数の値を変更できる。
class Final{
    final var name = "Ayako Sayama"
    init() { name = "Ayako Superman" }
}

//NG Compileエラー
class Student: Final{
    override var name = "new name"
}
```

### Final Method

*Finalメソッドはそのままなのでコードはスルーします。
要するに、中身を他の子クラスなどで、書き換えられないという感じです。