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