
I don't want anyone constructing a Party object on its own, so I want to make the constructor protected. I basically want these tests to pass:
assert_raise(NoMethodError) {Party.new("some name") }
end
d = Department.new("name")
assert_equal "name", d.name
end
e = Employee.new("name", 5, 12)
assert_equal "name", e.name
end
I first tried this:
attr_reader :name
@name = name
end
protected :initialize
end
But the initialize method can happily be called when constructing Party directly, so the first test fails. I then tried this:
attr_reader :name
@name = name
end
end
end
super(name)
@id, @annual_cost = id, annual_cost
end
end
super
end
end
which does prevent me from constructing Party directly. Unfortunately, I can't construct the concrete classes without getting a NoMethodError because I'm calling the protected method :new, so this isn't much good to me. But then Andy Kotlinski showed me that if I implement :new on both of the concrete classes to simply call super:
super(name)
@id, @annual_cost = id, annual_cost
end
; super; end
end
super
end
; super; end
end
And now all of the tests pass, and my superclass constructor is protected.
Now, if you don't want to jump through all of those hoops, you can include a module like this:
klass.module_eval do
end
end
end
end
include MakeConstructorProtected
attr_reader :name
@name = name
end
end
And you don't need to modify any of your subclasses. Because the inclusion of the module documents the intention far better than the obscure code, I quite like this solution. It still feels a little un-ruby-like, but it does document that Party wasn't written with the intention of being constructed on its own, and I quite like that. If anyone has an easier way to do this, then I'd love to hear it.
