Pythonのメソッドはオーバーライドされているのか


Javaではstaticメソッドはオーバーライドできないとされています。  
たとえば、以下のようなコードはオーバーライドではないとされています。  
(オーバーライドではなく、隠蔽(hiding)であるとされる)

[code]

    class A {
        public static void a() { 
            System.out.println("A.a()");
        }
    }   
    
    class B extends A {
        public static void a() {
            System.out.println("B.a()");
        }
    }
    
[/code]

  * [Overriding static methods in java](https://stackoverflow.com/questions/16617408/overriding-static-methods-in-java)
  * [Javaのドキュメンテーション](http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html)

* * *

一方、Pythonで似たようなコードを書いてみます。

[code]

    class A(object): 
        @staticmethod
        def a():
            print("A.a()")
    
    class B(A):
        @staticmethod
        def a():
            print("B.a()")
    
[/code]

これはオーバーライドなのでしょうか?

**質問:**

  * 上記のPythonコード例はオーバーライドと考えるべきか否か? その判断の根拠は?
  * staticmethodではなく、classmethodや普通のメソッドの場合は?
  * 一般に動的言語でどう考えるべきか? 




ちょっと乱暴な回答になりますが、より良い回答がつくまでのつなぎにどうぞ。

> 上記のPythonコード例はオーバーライドと考えるべきか否か? その判断の根拠は?

考えて良いでしょう。以下のコードでは、ベースクラス `A` にスタティックメソッド `a()` を呼び出すインスタンスメソッド `call_a()`
を追加し、`B` のインスタンスの `call_a()` を呼んだ時、`B.a()` が実行されています。これが根拠です。

[code]

    class A(object): 
        @staticmethod
        def a():
            print("A.a()")
    
        def call_a(self):
            self.a()
    
    class B(A):
        @staticmethod
        def a():
            print("B.a()")
    
    p = B()
    p.call_a()    # B.a()
    
[/code]

> staticmethodではなく、classmethodや普通のメソッドの場合は?

`classmethod` については同様の方法で実験してみてください。 普通のメソッドについては、当然オーバーライドとみなせます。

> 一般に動的言語でどう考えるべきか?

OOP の基本に立ち返ると「オーバーライドができる」というのは、 「あるメッセージに対する既存の振る舞いを変更=上書きできる」ということです。

最初の例はまさにそれを確認する作業で 仮に `call_a()` がBのインスタンスに対しても `A.a()` を呼び出すようならば、
これは振る舞いを変更できなかったことになるので、 オーバーライドできていないとなるわけです。

