# Primary and secondary constructors

**URL:** <https://forum.crystal-lang.org/t/primary-and-secondary-constructors/4172>\
**Category:** Help & Support\
**Created:** [December 21, 2021, 8:09pm UTC](https://forum.crystal-lang.org/t/primary-and-secondary-constructors/4172 "2021-12-21T20:09:21Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![hutou](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hutou/32/1337_2.png) [@hutou](https://forum.crystal-lang.org/u/hutou)\
**Post date:** [December 21, 2021, 8:09pm UTC](https://forum.crystal-lang.org/t/primary-and-secondary-constructors/4172/1 "2021-12-21T20:09:22Z")

</div>

Recently, I discovered Yegor Bugayenko’s books (Elegant objects vol 1 & 2) and his [blog](https://www.yegor256.com/2015/05/28/one-primary-constructor.html) 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.

```auto
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.

```auto
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?

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [December 21, 2021, 8:22pm UTC](https://forum.crystal-lang.org/t/primary-and-secondary-constructors/4172/2 "2021-12-21T20:22:43Z")

</div>

In Crystal this is handled via the differentiation between `def initialize` and `def self.new`. Usually the rule of thumb is use `self.new` overloads to transform the arguments to fit a smaller amount of `initialize` methods. E.g. your example could be written as:

```auto
class Test
  def self.new(f_or_s : Float64 | String) : self
    new f_or_s.to_i
  end
 
  def initialize(@value : Int32)
    raise ArgumentError.new "parameter error" if @value > 50
  end
end

```

Also checkout [Constructor variants and inheritance](https://forum.crystal-lang.org/t/constructor-variants-and-inheritance/3310), as it has some more detailed information on how the two relate, especially when inheritance is introduced.

---

<div class="post-metadata">

**Author:** ![hutou](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hutou/32/1337_2.png) [@hutou](https://forum.crystal-lang.org/u/hutou)\
**Post date:** [December 21, 2021, 9:06pm UTC](https://forum.crystal-lang.org/t/primary-and-secondary-constructors/4172/3 "2021-12-21T21:06:24Z")

</div>

In my examples (especially the first one), the question was whether there were several memory allocations for one object.  
I guess in your example this is not the problem anymore.  
Elegant syntax anyway, I didn’t know the use of `self.new`.  
Thanks

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [December 22, 2021, 9:52am UTC](https://forum.crystal-lang.org/t/primary-and-secondary-constructors/4172/4 "2021-12-22T09:52:01Z")

</div>

> [@hutou](#):
>
> the question was whether there were several memory allocations for one object.

Each object is only allocated once, no matter how often you call methods named `#initialize` on it. In fact, `#initialize` is really just a normal method. There are some special rules in the compiler to validate it assigns all instance variable. But it has no extra sauce at run time. You can call `#initialize` on an already initialized object (its visibility is protected, so that only works from the class or instance scope).

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [December 22, 2021, 9:56am UTC](https://forum.crystal-lang.org/t/primary-and-secondary-constructors/4172/5 "2021-12-22T09:56:06Z")

</div>

Regarding primary constructors, I agree that it’s a good idea. In Crystal (and Ruby) you’re encouraged to differentiate `#initialize` and `.new` which fit very well with the description of primary and secondary constructors.

There are however some limitations with inheritance which require to use `#initialize` as a secondary constructor (an example is stdlib’s `Socket` class tree).
