Multiple constructors in a idiomatic Ruby way. Small, fast, thread-safe, doesn't depend on other gems.
Use konstructor
keyword to declare constructors additional
to the default 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. Works with Ruby 1.9.3 or higher.
Via Gemfile:
gem 'konstructor'
and then execute bundle
.
You can also install it without Bundler:
$ gem install konstructor
If you are a gem author or just wish to manually include konstructor
keyword in your classes only when you need it, see
Manual include page.
In its simplest form konstructor
declaration 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_a_constructor
end
def create
end
def recreate
end
Declaration with method names can be placed anywhere in class definition.
def create
end
konstructor :create
konstructor
def recreate
end
Several declarations may be used, all declarations add up without overwriting each other.
def create
end
konstructor :recreate
konstructor :create
def recreate
end
In all above cases SomeClass
will have the default constructor
and two additional ones.
obj0 = SomeClass.new
obj1 = SomeClass.create
obj2 = SomeClass.recreate
If you decide to remove the default Ruby constructor for some reason,
you can achieve the effect by marking it private with Ruby
method private_class_method
:
class SomeClass
private_class_method :new
end
Additional constructors work exactly the same way as the default one.
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 declared as konstructor
in hierarchy,
it is always a constructor.
There are certain limitations to what can be declared as konstructor
,
see
Limitations page
for details.
Sometimes you don't want to completely replace the default constructor, instead you just want to add additional processing before/after it.
class Person
def initialize(name)
@name = name
@word_count = name.split(' ').size
end
konstructor
def from_two_names(first_name, second_name)
initialize(first_name + ' ' + second_name)
@name_count = 2
end
attr_reader :name, :word_count, :name_count
end
Person.new('John Doe')
Person.from_two_names('John', 'Doe')
Konstructor doesn't affect other gems depending on metaprogramming, such as rake, thor, contracts, etc.
For instnace, this is how Konstructor works with Contracts:
class SomeClass
konstructor
Contract Num => SomeClass
def create(some_number)
@number = some_number
end
end
obj0 = SomeClass.create(3)
obj1 = SomeClass.create("three") # raises contract exception
If you stumble upon a metaprogramming gem that conflicts with Konstructor, please open an issue.
The default Ruby constructor is a pair consisting of public
class method new
and a private instance
method initialize
. To create an additional one konstructor
marks given instance method as private and defines a
corresponding public class method with the same name.
Using konstructor
declaration has no runtime perfomance penalty,
since all work is done during class definition and then it's just
standard Ruby instance creation.
Cost of konstructor
declaration at initial load time is roughly the
same as declaring 5 properties with attr_accessor
.
attr_accessor :one, :two, :three, :four, :five
# following declaration takes the same time as above declaration
konstructor
def create
end
See Benchmarks page for details.
Konstructor doesn't depend on other gems. Requires Ruby 1.9.3 or higher. Works with JRuby.
Konstructor is thread-safe in both CRuby and JRuby, see Thread safety page for details.
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.
The gem is available as open source under the terms of the MIT License.