IThaiのブログ

IT関連の話題やタイに関する様々なことを書いていきます。

PythonとJavaのクラス、インスタンス、スコープの違いを比較

Pythonについて少し学んだので、復習を兼ねて忘れないために書き残しておきます。

1. Pythonのクラスは名前空間

クラスとインスタンスに同じ名前の属性を定義し、それぞれに異なる値を設定することができます。 下の例では、Testクラスの中にdata、また _ init _ メソッドの中にもdataという属性を定義しています。Testクラスのインスタンスを作成して呼び出して出力すると、それぞれ異なる値が設定されています。

*クラス内に定義したdefは関数ではなくメソッドと呼ばれ、必ず第1引数に自分のインスタンスself (Javaのthisのようなもの) を指定します。

Python
test.py

class Test:
    data = 'classData'                 #クラスの属性
    def __init__(self, d):
        self.data = d                      #インスタンスの属性
    def display(self):
        print self.data, Test.data

x = Test(1)
x.display()

実行結果:

1 classData

これがJavaだったら、クラス内のdataとコントラクタ内の(this.)dataは同じフィールドを示しているので、どちらも同じ値になります。下の例では、ほぼ同じコードを書くようにして実行してみました。

Java
Main.java

class Test {
    static String data = "classData";
    Test(String d) {
        this.data = d;
    }
    void display() {
        System.out.println(this.data + " " + Test.data);
    }
}

class Main {
    public static void main(String[] args) {
        Test test = new Test("1");
        test.display();
    }
}

実行結果:

1 1
2. メソッドの呼び出しは2通りある

(1)インスタンス属性へのアクセスする方法と、(2)クラスのメソッドを呼び出す方法があります。クラスのメソッドを呼び出す方法では、インスタンスを引数に渡してあげます。

Python
test.py

class Test:
    data = 'classData'
    def __init__(self, d):
        self.data = d
    def display(self):
        print self.data, Test.data

x = Test(1)
x.display()             #(1)インスタンス属性へのアクセス
y = Test(2)
Test.display(y)      #(2)クラスのメソッドの呼び出し

実行結果:

1 classData
2 classData
Java

Javaでは、Test.display()のコンパイルを通すには、display()をstaticのクラスメソッドとしなければならないです。(Test.display()とtest.display()を両方実行することはできない。)

3. 演算子のオーバーロード

Pythonでは、演算子のオーバーロードというものがあります。 例えば、 _ sub _ 、 _ add _ のようなメソッドです(フックメソッドというらしい)。

以下のように使います。

Python
class Test :
    def __init__ (self, d1) :
        self.data = d1
    def __sub__ (self, d2) :
        return Number(self.data - d2)

x = Test(3)
y = x - 2
print y.data

実行結果:

1
Java

Javaにはそもそも演算子をオーバーロードする機能がないので、比較は省略。

4. スコープの整理

pythonのスコープは、グローバル、モジュール、クラス、インスタンス、ローカルに分かれています。

Python
x = 'global or module'

def a():
    x = 'def local'
class A:
    x = 'class'
    def a(self):
        x = 'method local'
        self.x = 'instance'

print x         #global or module
print a()       #None
print A.x      #class
obj = A()  
obj.a()
print x          #global or module
print obj.x    #instance
print A.x       #class

実行結果:

global or module
None
class
global or module
instance
class
Java

Javaではクラス、インスタンス、ローカルに分かれます。グローバル領域にスコープはなく、モジュールとクラスが同じ領域になると思います。また、クラス変数とインスタンス変数に同じ名前を付けられません。

class Test {
    static String x = "class";
    String y = "instance";    // xをつけるとコンパイルエラー
    void a() {
        String x = "local";
        this.y = "instance";
    }
}

class Main2 {
    public static void main(String[] args) {
        System.out.println(Test.x);
        Test obj = new Test();
        System.out.println(obj.y);
        obj.a();
        System.out.println(Test.x);
        System.out.println(obj.y);
    }
}

実行結果:

class
init instance
class
call instance

PythonとJavaは同じオブジェクト志向言語でも、Pythonは動的に型を評価するスクリプト言語で、Javaは静的に型を評価するコンパイル型言語なので、かなり異なっている点があると思いました。今後も継続してPythonを勉強していきます。

パーフェクトRuby

パーフェクトRuby