javaとpythonの違いを列挙してみた

**※注意 気づいたものを順次追記する**

java屋さんがpythonを使いだして、違いにびっくりしたものを列挙する。
またその対処方法を残す。

# switch文

pythonにはswitchにあたる構文がない。
switchがなければifでやればいいじゃないという発想らしい。
もしくは辞書を使った方法もある。

[Python に switch や case 文がないのはなぜですか？(公式サイト)](https://docs.python.org/ja/3/faq/design.html#why-isn-t-there-a-switch-or-case-statement-in-python)

```python:辞書で使った方法
def function_1():
    print('function_1!')
def function_2():
    print('function_2!')

functions = {'a': function_1, 'b': function_2}

func = functions['b']
func()

↓実行結果↓
function_1!
```

# 定数

pythonには厳密な定数はなく、
全部大文字に命名することで運用的に定数のように扱う。
単なる変数なので当然その気になれば変更できる。

# インターフェイス

pythonにはインターフェイスが存在しない。
ABC(Abstract Base Classes)という抽象クラスの概念はあるので特に困らないかな。
全部抽象メソッドにすればいいだけ。

```python:抽象クラスの書き方(abctest.py)
from abc import ABC, abstractmethod

class Animal(ABC):
    @abstractmethod
    def sound(self):
        pass

class Cow(Animal):
    def sound(self):
        print("moo")

class Penguin(Animal):
    pass  # 抽象メソッドを実装していない

if __name__ == "__main__":
    hanako = Cow()
    hanako.sound()

    taro = Penguin()  # 抽象メソッドを実装していないのでインスタンス化時にエラーになる
```

```console:実行結果
moo
Traceback (most recent call last):
  File "abctest.py", line 19, in <module>
    taro = Penguin()
TypeError: Can't instantiate abstract class Penguin with abstract methods sound
```


# オーバーロード

pythonにはオーバーロードという概念がない。
オーバーロードのようなことをするには引数のデフォルト設定や可変長引数を使う。

#### オーバーロードしようとするとエラーになる例

```python:これはダメ
class Farm:
    def add(self, animal):
        print(animal)
    def add(self, animal1, animal2):
        print(animal1)
        print(animal2)

if __name__ == "__main__":
    farm = Farm()
    farm.add('Dog')
    farm.add('Jersey','Holstein')

↓実行結果↓
Traceback (most recent call last):
  File "farmtest.py", line 13, in <module>
    farm.add()
TypeError: add() missing 2 required positional arguments: 'animal1' and 'animal2'
```

#### これはOK

```python
class Farm:
    def add(self, animal='Chicken'):
        print(animal)

if __name__ == "__main__":
    farm = Farm()
    farm.add()
    farm.add('Dog')

↓実行結果↓
Chicken
Dog
```

```python
class Farm:
    def add(self, *args):
        if len(args) == 0:
            print('blank')
        for i in args:
            print(i)

if __name__ == "__main__":
    farm = Farm()
    farm.add()
    farm.add('Dog')
    farm.add('Jersey','Holstein')

↓実行結果↓
blank
Dog
Jersey
Holstein
```

# ApplicationContext

JavaのServletやspringframeworkでSessionスコープより広範囲のApplicationContextに該当するものはdjangoにはない。
djangoを使っているから？

# ラベル付きbreak

javaで2重ループから一気に抜け出すようなときに使うラベル付きbreakはpythonにない。
javaでもあまり使わないから、まいいか。

# ローカル変数の有効範囲(スコープ)

pythonは関数内有効。
javaはブロック内有効。

これは、、java屋さんからすると扱いづらい・・・。

# フィールド定義位置

javaのインスタンス変数のような書き方をするとpythonではクラス変数の意味になってしまうので注意！
最初うっかり書き間違えたら動きが想定外になってびっくりした。

```python:pythonだとこう
class Cow:
    type = 'Holstein'  # クラス変数
    def __init__(self, name): # コンストラクタ
        self.name = name  # インスタンス変数
    def walk(self):
        print(self.name + 'が歩く')

hanako = Cow('はなこ')
hanako.walk()

↓実行結果↓
はなこが歩く
```

```java:javaだとこう
class Cow {
    private static String type = "Holstein"  // クラス変数
    private String name; // インスタンス変数
    public Cow(String name) { // コンストラクタ
        this.name = name;
    }
    public void walk() {
        System.out.println(this.name + "が歩く");
    }    
}

class Main {
    public static void main(String[] args) {
        Cow hanako = new Cow("はなこ");
        hanako.walk();
    }
}

↓実行結果↓
はなこが歩く
```