Goal
- 抽象クラスを定義して、クラスの属性とメソッドをサブクラスに継承させたい
- サブクラスから抽象クラスの属性を上書きできるようにしたい
- サブクラスでクラス属性を上書きしなかった場合、抽象クラスで定義された属性をデフォルトで使用したい
- デザインパターン苦手科目ですが、(たぶん)テンプレートメソッドパターンと同じことができます
Code
class AbstractModel
@primary_key = nil
@table_name = 'abstract'
@storage = 'file'
class << self
attr_accessor :primary_key, :table_name, :storage
def inherited(klass)
klass.primary_key = @primary_key
klass.table_name = @table_name
klass.storage = @storage
end
end
def print_primary_key
p self.class.primary_key
end
def print_table_name
p self.class.table_name
end
end
class Person < AbstractModel
@primary_key = 'person_id'
@table_name = 'persons'
def print_storage
p self.class.storage
end
end
class Sport < AbstractModel
@primary_key = 'sport_id'
@table_name = 'sports'
def print_storage
p self.class.storage
end
end
##
## クラスメソッドからクラスの属性が取得できることを確認
##
p AbstractModel.primary_key
# nil
p Person.primary_key
# "person_id"
p Sport.primary_key
# "sport_id"
abs = AbstractModel.new
person = Person.new
sport = Sport.new
##
## 親クラスから継承されたインスタンスメソッドが使えること
## インスタンスメソッドからも自分のクラスの属性が取得できることを確認
##
abs.print_table_name
# "abstract"
person.print_table_name
# "persons"
sport.print_table_name
# "sports"
##
## サブクラスで上書きしていない属性にアクセスすると親クラスの値がデフォルトになっていることを確認
##
person.print_storage
# "file"
sport.print_storage
# "file"
親クラス(AbstractModel)で定義されたクラスインスタンス変数はサブクラス(Person, Sport)に継承されないが、クラスメソッドは継承される.
これはつまり、クラスインスタンス変数に対してattr_accessorを指定してやるとクラスインスタンス変数への入出力がメソッド化されるため、サブクラスに受け継ぐことができる(Person, Sportに対してprimary_key、primary_key=などのメソッドがよべる)ようになる.
けれども、これらの継承されたクラスメソッドが読み書きするのはサブクラス(Person, Sport)のクラスインスタンス変数なので、親クラス(AbstractModel)の属性をデフォルトとして使いたいならばinheritedを使うなどしてサブクラスのクラスインスタンス変数にコピーする必要がある.
また、インスタンスメソッドからクラスインスタンス変数を使うときには、メソッドのレシーバのクラスインスタンス変数に確実にアクセスできるようself.classをつけてよびだす.
もっとスマートな方法あれば教えて下さい.
References
以下の記事参考にさせていただきました.
http://qiita.com/a-suenami/items/bca7deefbe4ce9db103f
Environment
% uname -a
Linux *** 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
% ruby -v
ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-linux]
% cat /etc/issue
CentOS release 6.5 (Final)
Kernel \r on an \m