shadowtalker
shadowtalker

Reputation: 13893

Crystal: inheritance vs inclusion vs extension

I asked a more limited version of this question at In Crystal, what's the difference between inheritance and inclusion?, but I think I (and other readers) would benefit from a more comprehensive answer.

What are the differences between inheritance (with <), inclusion (with include), and extension (with extend) in Crystal classes?

Upvotes: 1

Views: 279

Answers (1)

shadowtalker
shadowtalker

Reputation: 13893

Answer

Class inheritance

Inheritance with < duplicates instance attributes, instance methods, class attributes, and class methods from the inherited class into the current class.

Modules cannot inherit or be inherited.

class A
  # Equivalent to `@@foo = 1` with corresponding getter and setter class methods
  @@foo = 1

  # Equivalent to `@foo = ` with corresponding getter and setter instance methods
  @foo = 2
end

class B < A
end

pp A.foo == B.foo  # true
pp A.new.foo == B.new.foo  # true

The value of a class attribute in the superclass is not the same as the value in the subclass, but the types will be the same.

class C
  class_property foo = 1
end

class D < C
end

D.foo = 9
pp C.foo == D.foo  # false

A class can inherit from exactly one class.

Module inclusion

include duplicates instance attributes and instance methods from the included module into the current class or module.

Classes cannot be included.

It is possible to define class attributes and class methods on modules, but these are not duplicated by inclusion; they are ignored.

module BirdHolder
  # Ignored by `include`
  class_property bird = "123"
  property bird = "456"
end

class Thing
  include BirdHolder
end

pp Thing.new.bird  # "456"
pp Thing.bird  # Error: undefined method 'bird' for Thing1.class

A type (module or class) can include any number of modules.

Module extension

extend duplicates instance methods from the included module into the current class or module, but as class methods.

Classes cannot be extended.

Class attributes and class methods from the extended module are ignored.

module Talkative
  # Ignored by `extend`
  @@stuff = "zxcv"

  # Ignored by `extend`
  def self.say_stuff
    puts "stuff"
  end

  def say_stuff
    puts @@stuff
  end
end

class Thing
  extend Talkative
  @@stuff = "asdf"
end

Thing.say_stuff  # "asdf"

Note that @@stuff in the definition of the Talkative module refers to the class attribute of the extending class, not to the class attribute of Talkative itself.

It is not possible to extend a module that defines instance methods. This results in a compilation error.

A type (module or class) can extend exactly one module.

References

This information is based on:

This answer is valid as of Crystal 1.0.0

Upvotes: 2

Related Questions