Explicitly setting iVar class in Ruby (ala Obj-C) -
i'm experienced obj-c/java programmer, , getting ruby. fact it's dynamic great (re-opening classes awesome!) there's 1 thing bugs me/worries me when start writing ruby code.
i'd interested know ruby-ers (if anything) explicitly set type of ivars in own classes. can see, can set ivar object , ruby won't complain. if expect specific ivar of type, can cause problems down line. example:
class mystring def initialize(mystring) @mystring = mystring end def uppercase_my_string @mystring.upcase end end st1 = mystring.new("a string!") st1.uppercase_my_string st2 = mystring.new(["a string"]) st2.uppercase_my_string this code throw nomethoderror, since of course array has no method upcase. unfortunately doesn't tell went wrong (the line above, when creating str2) we're not helped when debugging (if str2 happens created several modules away in inconspicuous place) 1 natural step might add checks initialize follows:
class mystring def initialize(mystring) raise typeerror, "mystring ivar not string!" unless mystring.class == string @mystring = mystring end end ...same code before great, if accidentally create new mystring we're told how silly (and more importantly we're told when , not when fail. bit of pain type it's ok. next problem when decide use attr_accessors on ivar.
class mystring attr_accessor :my_string def initialize(my_string) raise typeerror, "mystring ivar not string!" unless my_string.class == string @my_string = my_string end def uppercase_my_string @my_string.upcase end end st1 = mystring.new("a string!") st1.uppercase_my_string st2 = mystring.new("good, it's string") st2.my_string = ["an array!"] st2.uppercase_my_string using setter defined, can sneaky , round error checking in initialize. once again has problem of throwing exception in uppercase_my_string , not when accidentally set @my_string array.
finally, create accessors manually , add error checking massive pain... there quicker , easier way this. or being closed minded , not dynamic enough?
thanks!
aside: know in obj-c still have same problem @ runtime, typically you'll spot compiler error saying you're assigning object of type array variable of type string (or similar), @ least we're warned happens
in practice these sorts of type problems pretty rare. if want paranoid (since they you), can send input through to_s ensure have string:
def initialize(my_string) @my_string = my_string.to_s end then can mystring.new(6) , work expected. of course, can mystring.new([6, 11]) , nonsense.
if want my_string string wouldn't explicitly check class. cause problems if has subclassed string you'd want @ least use is_a?:
def initialize(mystring) raise typeerror, ... unless mystring.is_a? string @mystring = mystring end there's to_str method check:
def initialize(mystring) raise typeerror, ... unless mystring.respond_to? :to_str @mystring = mystring.to_str end implementing method (in circles) indicate thing string-like enough string. think calling to_s better idea though, make things behave more people expect in ruby.
as far mutator problem concerned:
st2.my_string = ["an array!"] you don't have let write want properties: classes aren't structs. automatically define accessor , write own mutator automatically slip in to_s call:
class mystring attr_reader :my_string def initialize(my_string) self.my_string = my_string end def my_string=(s) @my_string = s.to_s end def uppercase_my_string @my_string.upcase end end basically, don't worry types in ruby, worry methods responds to. and, if want string, make string calling universal to_s method (which string interpolation, "#{x}", do).
Comments
Post a Comment