Reputation: 13893
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
Reputation: 13893
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.
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.
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.
This information is based on:
crystal-lang/crystal
Gitter chatroom.This answer is valid as of Crystal 1.0.0
Upvotes: 2