Konstructor
Konstructor is a small gem that gives you multiple constructors in Ruby.
Use konstructor keyword to define constructors additional to the defaul one:
class SomeClass
konstructor
def create(val)
@val = val
end
attr_reader :val
end
obj0 = SomeClass.new
obj0.val # nil
obj1 = SomeClass.create(3)
obj1.val # 3
It's similar to having overloaded constructors in other languages.
Installation
Via Gemfile:
gem 'konstructor'
and then execute bundle.
You can also install it without Bundler:
$ gem install konstructor
If you wish to manually include Konstructor in your classes only when you need it, see Manual include page.
Usage
In simplest form konstructor creates a constructor from the next method.
konstructor
def create
end
konstructor
def recreate
end
When method names are given, it creates constructors from those methods without affecting the next method.
konstructor :create, :recreate
def not_constructor
end
def create
end
def recreate
end
Call with method names can be placed anywhere in class definition.
def create
end
konstructor :create
konstructor
def recreate
end
In all above cases the class will have the default constructor and two additional ones.
obj0 = SomeClass.new
obj1 = SomeClass.create
obj2 = SomeClass.recreate
Same as default constructor
Additional constructors work exactly the same way as built-in Ruby constructor.
You can pass blocks to them.
konstructor
def create(val)
@val = yield val
end
obj = SomeClass.create(3) { |v| v*3 }
obj.val # 9
You can override them in subclasses and call super.
class SomeClass
konstructor
def create(val)
@val = val
end
attr_reader :val
end
class SomeSubclass < SomeClass
def create(val1, val2)
super(val1 * val2)
end
end
obj = SomeSubclass.create(2, 3)
obj.val # 6
Once method is a marked as konstructor in hierarchy, it is always a konstructor.
Methods inherited from superclasses can't become konstructors in subclasses. To achieve the effect, define a new method, mark it as konstructor and call the inherited one.
Reserved names
Using reserved method names new and initialize for additional
constructor declaration will raise an error:
konstructor
def initialize # raises Konstructor::ReservedNameError
end
or
konstructor
def new # raises Konstructor::ReservedNameError
end
Defining konstructors in Modules
Modules can't have konstructors. Use ActiveSupport::Concern and
define konstructor in included block.
Using with other gems
Konstructor doesn't affect other gems, including those that depend on metaprogramming, such as rake, thor, contracts, etc.
For instnace, this is how Konstructor works with contracts gem:
class SomeClass
konstructor
Contract Num => SomeClass
def create(some_number)
@number = some_number
end
end
If you stumble upon a metaprogramming gem that conflicts with Konstructor, please open an issue.
Removing default constructor
You can effectively remove default Ruby constructor by marking it as private:
class SomeClass
private_class_method :new
end
Performance
Konstructor does all its work when class is being defined. Once class has been defined, it's just standard Ruby instance creation. Therefore, there is no runtime performance penalty.
Konstructor doesn't depend on other gems.
Thread safety
Konstructor is thread safe.
Details
Ruby constructor is a pair consisting of public factory method defined
on a class and a private instance method. Therefore, to achieve
its goal konstructor marks instance method as private and defines a
corresponding public class method with the same name.
You can check if certain instance method name has been declared as constructor or is a default constructor by running.
Konstructor.is?(SomeClass, :initialize) # true
Konstructor.is?(SomeClass, :create) # true
Konstructor.is?(SomeClass, :recreate) # true
Konstructor.is?(SomeClass, :something_else) # false
It will return true even if no such constructor has been defined yet. Like:
class SomeClass
konstructor :create
end
Konstructor body may be supplied in subclasses.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/snovity/konstructor. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
License
The gem is available as open source under the terms of the MIT License.