使用多级继承而不是 ruby mixins
Using multi-level inheritance instead of ruby mixins
这里有一个多级继承的例子ruby,这里有3个classA,B,C,B继承A,C继承B,所以在最后classC有A、B、C的所有方法
class A
def hello_by_a
puts "A says hello"
end
end
class B < A
def hello_by_b
puts "B says hello"
end
end
class C < B
def hello_by_c
puts "C says hello"
end
end
c = C.new
c.hello_by_a #=> A says hello
c.hello_by_b #=> B says hello
c.hello_by_c #=> C says hello
p c.methods-Object.methods #=> [:hello_by_c, :hello_by_b, :hello_by_a]
这和 mixin 是一样的,这里不是 classes A 和 B,我们有模块 A 和 B,它们包含在 class C 中。现在 class C 有所有 3 种方法
module A
def hello_by_a
puts "A says hello"
end
end
module B
def hello_by_b
puts "B says hello"
end
end
class C
include A
include B
def hello_by_c
puts "C says hello"
end
end
c = C.new
c.hello_by_a #=> A says hello
c.hello_by_b #=> B says hello
c.hello_by_c #=> C says hello
p c.methods-Object.methods #=> [:hello_by_c, :hello_by_b, :hello_by_a]
最后如果我们两种方式都做 class C 将拥有 class A 和 B 或模块 A 和 B 的所有方法。那么为什么使用模块更好呢? classes?
的多级继承
我知道我们应该使用 mixins 但真的不知道为什么我们不应该像上面那样使用多级继承。有什么缺点和优点。如果有的话?
两个主要原因:
您只能继承一个 class,但您可以根据需要混入任意多个混入。这意味着继承是极其 "expensive" 的,如果你被迫使用继承,你将被迫 "use up" 100% 的 "inheritance resources".
您可以按照自己的方式编写混合宏。在你的例子中,我只能得到A
的方法,A
的方法∪B
,A
的方法∪B
∪C
。例如,我不能只获取 B
的方法。使用 mixin,我可以将它们组合成任意组合:仅 A
、仅 B
、仅 C
、A
∪ B
、A
∪ C
、B
∪ C
和 A
∪ B
∪ C
。我也可以按照我想要的任何 顺序 组合它们:我可以让 C
的方法覆盖 B
的方法,或者我可以让 B
覆盖 C
.
的方法
我可以很容易地想象一个既是 Enumerable
and Comparable
. (For example, String
s are Comparable
and before Ruby 1.9, they also used to be Enumerable
.) In your proposed world, this would only be possible if either Enumerable
inherits from Comparable
or Comparable
inherits from Enumerable
. However, this will not work: Numeric
s are Comparable
but not Enumerable
, Array
又是 Enumerable
但不是 Comparable
的对象。
还有一个更哲学/语义的原因:可枚举性和可比性是完全正交的概念,为什么会你把他们绑的这么紧?继承是我们拥有的最接近的耦合形式之一,将两个实际上彼此没有任何关系的概念紧密地联系在一起,只是错误。
这里有一个多级继承的例子ruby,这里有3个classA,B,C,B继承A,C继承B,所以在最后classC有A、B、C的所有方法
class A
def hello_by_a
puts "A says hello"
end
end
class B < A
def hello_by_b
puts "B says hello"
end
end
class C < B
def hello_by_c
puts "C says hello"
end
end
c = C.new
c.hello_by_a #=> A says hello
c.hello_by_b #=> B says hello
c.hello_by_c #=> C says hello
p c.methods-Object.methods #=> [:hello_by_c, :hello_by_b, :hello_by_a]
这和 mixin 是一样的,这里不是 classes A 和 B,我们有模块 A 和 B,它们包含在 class C 中。现在 class C 有所有 3 种方法
module A
def hello_by_a
puts "A says hello"
end
end
module B
def hello_by_b
puts "B says hello"
end
end
class C
include A
include B
def hello_by_c
puts "C says hello"
end
end
c = C.new
c.hello_by_a #=> A says hello
c.hello_by_b #=> B says hello
c.hello_by_c #=> C says hello
p c.methods-Object.methods #=> [:hello_by_c, :hello_by_b, :hello_by_a]
最后如果我们两种方式都做 class C 将拥有 class A 和 B 或模块 A 和 B 的所有方法。那么为什么使用模块更好呢? classes?
的多级继承我知道我们应该使用 mixins 但真的不知道为什么我们不应该像上面那样使用多级继承。有什么缺点和优点。如果有的话?
两个主要原因:
您只能继承一个 class,但您可以根据需要混入任意多个混入。这意味着继承是极其 "expensive" 的,如果你被迫使用继承,你将被迫 "use up" 100% 的 "inheritance resources".
您可以按照自己的方式编写混合宏。在你的例子中,我只能得到A
的方法,A
的方法∪B
,A
的方法∪B
∪C
。例如,我不能只获取 B
的方法。使用 mixin,我可以将它们组合成任意组合:仅 A
、仅 B
、仅 C
、A
∪ B
、A
∪ C
、B
∪ C
和 A
∪ B
∪ C
。我也可以按照我想要的任何 顺序 组合它们:我可以让 C
的方法覆盖 B
的方法,或者我可以让 B
覆盖 C
.
我可以很容易地想象一个既是 Enumerable
and Comparable
. (For example, String
s are Comparable
and before Ruby 1.9, they also used to be Enumerable
.) In your proposed world, this would only be possible if either Enumerable
inherits from Comparable
or Comparable
inherits from Enumerable
. However, this will not work: Numeric
s are Comparable
but not Enumerable
, Array
又是 Enumerable
但不是 Comparable
的对象。
还有一个更哲学/语义的原因:可枚举性和可比性是完全正交的概念,为什么会你把他们绑的这么紧?继承是我们拥有的最接近的耦合形式之一,将两个实际上彼此没有任何关系的概念紧密地联系在一起,只是错误。