In Crystal, my experience using initialize
is that it obstructs all superclass constructors:
class Mammal
property name = "unnamed"
def initialize(name)
@name = name
end
end
class Dog < Mammal
getter breed = "unknown"
def initialize(name, breed)
@name = name
@breed = breed
end
end
sadie = Dog.new("Sadie")
Error in line 18: wrong number of arguments for 'Dog.new' (given 1, expected 2)
Overloads are:
- Dog.new(name, breed)
That seems like reasonable compiler behavior, but what if I want to avoid repeating myself (e.g. if there are several shared constructors across several subclasses)? There are a couple options.
I could use the inherited macro:
class Mammal
property name = "unnamed"
macro inherited
def initialize(name)
@name = name
end
end
end
class Dog < Mammal
getter breed = "unknown"
def initialize(name, breed)
@name = name
@breed = breed
end
end
sadie = Dog.new("Sadie")
I could use self.new
in the subclass instead of initialize
:
class Mammal
property name = "unnamed"
def initialize(name)
@name = name
end
end
class Dog < Mammal
getter breed = "unknown"
def self.new(name, breed)
self.name = name
self.breed = breed
end
end
sadie = Dog.new("Sadie")
I could add an extra, catch-all initialize
:
class Mammal
property name = "unnamed"
def initialize(name)
@name = name
end
end
class Dog < Mammal
getter breed = "unknown"
def initialize(name, breed)
@name = name
@breed = breed
end
def initialize(*args)
super(*args)
end
end
sadie = Dog.new("Sadie")
There may very well be other options. Among the aforementioned choices (and any others that you may know of), is there a “best” solution to this problem? I could certainly just repeat code on every subclass, but that violates DRY, so I’d like to avoid that. Also, please assume that my use case necessitates that at least one of the subclasses must have a new constructor.
Postscript: I know is isn’t really asking for help with a problem, but this seemed like the appropriate category. Please move it if that is not the case.