Crystal:继承 vs 包含 vs 扩展

Crystal: inheritance vs inclusion vs extension

我在 问了这个问题的更有限的版本,但我认为我(和其他读者)会从更全面的答案中受益。

继承(with<)、inclusion(withinclude)有什么区别, extension (with extend) in Crystal 类?

回答

Class继承

继承 < 从继承的 class[=76= 复制实例属性、实例方法、class 属性和 class 方法] 到当前 class.

模块不能继承或被继承。

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

superclass 中 class 属性的值与 subclass 中的值不同,但类型相同。

class C
  class_property foo = 1
end

class D < C
end

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

一个class可以继承自一个class。

模块包含

include 将包含的 模块 中的实例属性和实例方法复制到当前的 class 或模块中。

Class无法包含。

可以在模块上定义 class 属性和 class 方法,但是这些 不是 通过包含复制的;他们被忽略了。

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

一种类型(模块或 class)可以包含任意数量的模块。

模块扩展

extend 将包含的 模块 中的实例方法复制到当前 class 或模块中,但作为 class 方法。

Class无法扩展。

来自扩展模块的

Class 属性和 class 方法被忽略。

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"

注意Talkative模块定义中的@@stuff指的是扩展classclass属性,而不是 Talkative 本身的 class 属性。

无法扩展定义实例方法的模块。这会导致编译错误。

一种类型(模块或class)只能扩展一个模块。

参考资料

此信息基于:

此答案自 Crystal 1.0.0

起有效