インスタンスにだけmoduleをインクルードすることで実現する.
ruby の include を使ってみることにしました。
ruby2.5.0 instance method Module#include
extendを使います。
ruby リファレンス extend
参考資料:Qiita::いつも忘れるRubyの include, prepend, extend の意味。そしてActiveSupport::Concernについても。
# 今回の例では人間を使います。
class Human
def initialize(name)
@name = name
end
end
# 人間は別名をいろいろ持っているのでこちらのmoduleでそれを設定できるようにしようと思います。
module OtherNames
attr_reader :nickname, :pseudonym, :twitter_name # アクセサはなくても平気です。
def set_nickname(nickname)
# 宣言するときにチェインできるようにtapを使います。
tap { @nickname = nickname }
end
# pseudonym は ペンネームのことだそうです。
def set_pseudonym(pseudonym)
tap { @pseudonym = pseudonym }
end
def set_twitter_name(twitter_name)
tap { @twitter_name = twitter_name }
end
end
# taroを用意します。
taro = Human.new('taro')
.extend(OtherNames)
.set_nickname('tarohiko')
.set_pseudonym('taronosuke')
.set_twitter_name('卍とんかつDJほげ☆太郎卍')
# 対照実験用にhanakoも用意しました。
hanako = Human.new('hanako')
# 同じクラスが生成元です
taro.class #=> Human
hanako.class #=> Human
# インスタンス変数を比較すると以下のようになっていました。
taro.instance_variables #=> @name, @nickname, @pseudonym, @twitter_name
hanako.instance_variables #=> @name
これで特定のインスタンスにのみ特定のインスタンス変数を持たせることができました。
extendの新境地に達しました。
追記(2018/07/18)
もともとincludeにしていたんですが、クラスをレシーバにしてincludeを利用するとクラスに対してのincludeとなっており、狙いである特定のインスタンスへのmoduleの追加ができていませんでした。
こちらはextendで実装可能でしたので修正しました。m(_ _)m