From: Christoph Date: 2002-09-12T05:58:29+09:00 Subject: Re: private variables "Paul Brannan" wrote in .... > I doubt there are many people who begin their instance variable names > with "@_"; those that do probably don't intend for the variable to be > accessed by derived classes anyway. Are you sure? I like @_vars and never associated the use of a ``_'' prefix with being ``private" until this discussion. We also could use your ``secret'' method frame work (it simulates private methods of C++ right?) and only implement ``private_attributes'' or "secret_attribute"? Here is a half baked Ruby implementation (without your secret_method stuff). /Christoph ---- module PrivateAttribute def instance_variables # needs more work super() - type.instance_eval { @__private_attributes + @__shadow } end class << self # helper methods def mangle(klass,sym) "__pa__#{klass.id}_#{sym.to_s}" end #actuall code private def append_features(klass) Class === klass or raise TypeError, "Expected klass .." super end def included(klass) klass.instance_eval { @private_attributes = [] @__private_attributes = [] @__shadow = [] } class << klass attr_reader :private_attributes private def private_attribute(attr) # silly tests unless String === attr or Symbol === attr raise TypeError, "expected ..." end attr = attr.to_s class_eval <<-PRIVATE_ATTR def #{attr} @#{PrivateAttribute.mangle(self,attr)} end def set_#{attr}(x) @#{PrivateAttribute.mangle(self,attr)} = x end PRIVATE_ATTR @private_attributes << attr @__private_attributes << "@" + PrivateAttribute.mangle(self,attr) end def inherited(sub_klass) tmp = @__private_attributes sub_klass.instance_eval { @private_attributes = [] @__private_attributes = [] @__shadow = tmp } @private_attributes.each {|attr| sub_klass.class_eval <<-INHERITED def #{attr} raise NoMethodError, "privacy violation of ..." end def set_#{attr}(x) raise NoMethodError, "privacy violation of ..." end INHERITED } # potenieal source of conflict with other mixins # like singleton super end end end end end class A include PrivateAttribute private_attribute :xxx def initialize(x) set_xxx x end end ##### a = A.new "a" a.instance_eval { @me = "me" } p a.instance_variables p A.private_attributes class B < A private_attribute :yyy def initialize(a) set_yyy a # super(a) end end b = B.new "b" p b.yyy p b.instance_eval { @you = "you" } p b.instance_variables p B.private_attributes class B def initialize(a) super a end end B.new ("boom") # NoMethodError --- ["@me"] ["xxx"] "b" "you" ["@you"] ["yyy"] (eval):5:in `set_xxx': privacy violation of ... (NoMethodError) from D:\Ruby\mswin\samples\rb58.tmp:84:in `initialize' from D:\Ruby\mswin\samples\rb58.tmp:111:in `initialize' from D:\Ruby\mswin\samples\rb58.tmp:114:in `new' from D:\Ruby\mswin\samples\rb58.tmp:114