Recently, I discovered Yegor Bugayenko’s books (Elegant objects vol 1 & 2) and his blog about object-oriented programming.
His statements are often described as controversial, but at the same time, they are thought-provoking!
One of his tips poses the problem of class constructors and he distinguishes between the primary constructor and the secondary constructors, the latter always ending up calling the primary constructor (which could for example centralize the validity check of instantiation parameters).
Here is an example in a first version, where initialize
calls initialize
, and reading the Crystal documentation, I’m afraid it’s not very satisfactory, even if it works.
class Test
def initialize(s : String) # Secondary constructor
initialize(s.to_i)
end
def initialize(f : Float64) # Secondary constructor
initialize(f.to_i)
end
def initialize(@value : Int32) # primary constructor, at end of list
raise "parameter error" if @value > 33
end
end
x = Test.new("33")
p! x
x = Test.new(3.14)
p! x
x = Test.new(42)
p! x
and here is a modified example, in which the initialize
method is called only once.
class Test
def initialize(s : String) # Secondary constructor
primary_initialize(s.to_i)
end
def initialize(f : Float64) # Secondary constructor
primary_initialize(f.to_i)
end
def initialize(i : Int32) # secondary constructor
primary_initialize(i)
end
def primary_initialize(i : Int32) # primary constructor
raise "parameter error" if i > 33
@value = i
end
end
x = Test.new("33")
p! x
x = Test.new(3.14)
p! x
x = Test.new(42)
p! x
Would there be another more efficient and/or idiomatic version to comply with this advice?
What do you think about it?