basyura's blog

あしたになったらほんきだす。

クラス変数とクラスインスタンス変数

メタプログラミングRuby

メタプログラミングRuby

Amazon

クラス変数がクラスに属していないからだ。クラスではなく、クラス階層に属しているのだ。
・・・略・・・
多くの Rubyist はクラス変数を使わずにクラスインスタンス変数を使っている。

main のコンテキストで定義されたクラス変数は置いとくとして、Java 上がりとしては、なんだそれって感じ・・・。
クラス変数を使った場合

class A
  @@name = 'original name'
  def self.name
    @@name
  end
  def self.name=(name)
    @@name = name
  end
end

class B < A
end

puts A.name #=> class_instance_variable
puts B.name #=> class_instance_variable
A.name = 'new name'
B.name = 'B name'
puts A.name #=> B name
puts B.name #=> B name

クラス変数の変更はサブクラスにも影響する。
クラスインスタンス変数を使った場合

class A
  @name = 'original name'
  def self.name
    @name
  end
  def self.name=(name)
    @name = name
  end
end

class B < A
end

puts A.name #=> original name
puts B.name #=> nil
A.name = 'new name'
B.name = 'another name'
puts A.name #=> original name
puts B.name #=> another name

クラスインスタンス変数の場合は継承関係に影響しない。
で、java ってどうだったっけと不安になったので確認。

public class Succession {
    public static String name = "original name";
}
public class SubSuccession extends Succession {
}
public class Main {
  public static void main(String args[]) {
        System.out.println(Succession.name);    //=> original name
        System.out.println(SubSuccession.name); //=> original name
        Succession.name    = "new name";
        SubSuccession.name = "another name";
        System.out.println(Succession.name);    //=> "another name"
        System.out.println(SubSuccession.name); //=> "another name"
  }
}

Java もサブクラスに影響する。Java の挙動って "こんな動きだったっけ?" と違和感を感じるのはなんだろう。static な変数をサブクラスが意識して使うってシチュエーションが無い(ほとんど使ったことが無い)からだろうか。
Java でクラスインスタンス変数は・・・ないなぁ。static な変数のスコープを private にしてサブクラスからは触らせないようにする程度か。
Ruby のクラスインスタンス変数も使いどころがよく分からないのはメタプログラミングしてないからか。