Ruby 继承和类型化
Ruby inheritance and typing
我对 Ruby 中的一些基本概念有疑问,特别是子class 与超级class 的互换性。
根据 classes 上的 Ruby 文档,"Class" 继承自 "Module"。
https://ruby-doc.org/core-2.5.3/Class.html
class MyClassTest end
MyClassTest.is_a? Module # => true
但是,当尝试使用 module
关键字重新打开使用关键字 class
定义的 class 时,您会得到一个 TypeError,表明 class 不是模块。
class MyClassTest end
module MyClassTest end # => TypeError: MyClassTest is not a module
这个 SO 问题围绕子 classes 与子类型进行了一些精彩的讨论,但我认为它让我想到了更多问题:
Why can't classes be used as modules?
一般来说,由于Ruby是动态类型的,我对TypeErrors的存在感到困惑。
具体来说,在这种情况下,我对 Ruby 继承如何导致无法用 subclass 替换 superclass 的 TypeError 感到非常困惑。在我看来,subclassing 等同于 Ruby 中的子类型,因为 subclass 将继承 super[=39= 的接口(方法和 public 属性) ].
我目前的猜测是,当某些断言失败时,核心 Ruby 库会引发 TypeError,而这些 TypeError 不一定与 Ruby 的动态类型系统有任何关系,也就是说打字不是 Ruby 中的第一个 class 概念。链接的 SO 问题提出了关于具有多个 class 继承的菱形问题的优秀观点,因此 Ruby 会阻止模块和 classes 在使用 [=13] 时的可互换使用是有道理的=] 或 class
关键字。不过,感觉我对Ruby.
的理解有些矛盾
当预期 "Module" 对象时,"Class" 输入如何导致 TypeError?
基本断言是
Class
是一个 Class
(Class.is_a?(Class) #=> true
)
Class
是一个 Module
(Class.is_a?(Module) #=> true
)
- class
Class
的实例是 Class
(Class.new.is_a?(Class) #=> true
)
- class
Class
的实例是 Module
(Class.new.is_a?(Module) #=> true
)
Module
是一个 Class
(Module.is_a?(Class) #=> true
)
- 凭借
Module
是一个Module
(Module.is_a?(Module) #=> true
)
- class
Module
的实例是 Module
(Module.new.is_a?(Module) #=> true
)
- 但是 class
Module
的实例不是 Class
(Module.new.is_a?(Class) #=> false
)
- class 的实例
Class
是 Class
的实例,但不是 class Module
的实例(Class.new.instance_of?(Module) #=> false
)
module
是 class Module
实例的声明,正如 class
是 class Class
.
如果这是一种方法,它可能看起来像
def module(name,&block)
raise TypeError if defined?(name) && !const_get(name).instance_of?(Module)
obj = defined?(name) ? const_get(name) : const_set(name, Module.new)
obj.instance_eval(&block)
end
TypeError
的存在是为了防止歧义。
与您的情况一样,通过使用 class MyClassTest
,您已经创建了 class Class
的一个实例,该实例称为 MyTestClass
。
如果您也被允许在同一个全局上下文中使用 module MyTestClass
,那么在使用过程中我将不知道在调用 MyClassTest
时我是否会调用 Class
或Module
。
基本(非常基本)区别是 Class
可以实例化(有实例)但是 Module
不能。
例如
Class.new.new #creates an instance of the anonymous class created by Class.new
Module.new.new # results in NoMethodError
我认为混淆的第一点是用法和定义之间的区别。
下面的代码定义一个class:
class C; end
如果我看到上面的代码,希望以后能够实例化C:
C.new
但是,假设 C 已经被定义为一个模块:
# In one file:
module C; end
# Later in a different file:
class C; end # C is actually a module
C.new # fails
Ruby 在 C 被重新定义为 class 的地方出现了问题(C 的定义冲突),而不是让程序继续到使用 C 的地方。
尽早发现问题的好处通常是越早发现错误,就越容易找到并修复其根本原因(在这个例子中,也许 C 应该是 class所有,因此真正的问题是 module C
定义)。
你的第二个问题是,我认为,为什么 class 不能 always 用作模块,例如为什么禁止以下内容:
class C; end
class A
include C
end
我认为,答案是编程语言以 概念 开始,然后使用各种构造 实现 。我们可以描述 classes 和模块如下:
- A class 表示具有数据和行为的对象(classic OOP 定义)。
- 模块是行为的集合。
include
关键字使用模块的 行为 扩展了 class。原则上,可以只采用 class 的方法并将它们添加到另一个 class。但是这个操作没有意义因为class是一个对象和它的行为在一起。只采取行为违背了 class.
的概念
还有其他编程语言在这个问题上采取不同的立场。例如,在 JavaScript 中,任何函数都可以从任何 class 中取出,并使用任何其他 class 的实例调用。这在某些情况下很方便,但在其他情况下却很难调试。
我对 Ruby 中的一些基本概念有疑问,特别是子class 与超级class 的互换性。
根据 classes 上的 Ruby 文档,"Class" 继承自 "Module"。 https://ruby-doc.org/core-2.5.3/Class.html
class MyClassTest end
MyClassTest.is_a? Module # => true
但是,当尝试使用 module
关键字重新打开使用关键字 class
定义的 class 时,您会得到一个 TypeError,表明 class 不是模块。
class MyClassTest end
module MyClassTest end # => TypeError: MyClassTest is not a module
这个 SO 问题围绕子 classes 与子类型进行了一些精彩的讨论,但我认为它让我想到了更多问题: Why can't classes be used as modules?
一般来说,由于Ruby是动态类型的,我对TypeErrors的存在感到困惑。
具体来说,在这种情况下,我对 Ruby 继承如何导致无法用 subclass 替换 superclass 的 TypeError 感到非常困惑。在我看来,subclassing 等同于 Ruby 中的子类型,因为 subclass 将继承 super[=39= 的接口(方法和 public 属性) ].
我目前的猜测是,当某些断言失败时,核心 Ruby 库会引发 TypeError,而这些 TypeError 不一定与 Ruby 的动态类型系统有任何关系,也就是说打字不是 Ruby 中的第一个 class 概念。链接的 SO 问题提出了关于具有多个 class 继承的菱形问题的优秀观点,因此 Ruby 会阻止模块和 classes 在使用 [=13] 时的可互换使用是有道理的=] 或 class
关键字。不过,感觉我对Ruby.
当预期 "Module" 对象时,"Class" 输入如何导致 TypeError?
基本断言是
Class
是一个Class
(Class.is_a?(Class) #=> true
)Class
是一个Module
(Class.is_a?(Module) #=> true
)- class
Class
的实例是Class
(Class.new.is_a?(Class) #=> true
) - class
Class
的实例是Module
(Class.new.is_a?(Module) #=> true
) Module
是一个Class
(Module.is_a?(Class) #=> true
)- 凭借
Module
是一个Module
(Module.is_a?(Module) #=> true
) - class
Module
的实例是Module
(Module.new.is_a?(Module) #=> true
) - 但是 class
Module
的实例不是Class
(Module.new.is_a?(Class) #=> false
) - class 的实例
Class
是Class
的实例,但不是 classModule
的实例(Class.new.instance_of?(Module) #=> false
)
module
是 class Module
实例的声明,正如 class
是 class Class
.
如果这是一种方法,它可能看起来像
def module(name,&block)
raise TypeError if defined?(name) && !const_get(name).instance_of?(Module)
obj = defined?(name) ? const_get(name) : const_set(name, Module.new)
obj.instance_eval(&block)
end
TypeError
的存在是为了防止歧义。
与您的情况一样,通过使用 class MyClassTest
,您已经创建了 class Class
的一个实例,该实例称为 MyTestClass
。
如果您也被允许在同一个全局上下文中使用 module MyTestClass
,那么在使用过程中我将不知道在调用 MyClassTest
时我是否会调用 Class
或Module
。
基本(非常基本)区别是 Class
可以实例化(有实例)但是 Module
不能。
例如
Class.new.new #creates an instance of the anonymous class created by Class.new
Module.new.new # results in NoMethodError
我认为混淆的第一点是用法和定义之间的区别。
下面的代码定义一个class:
class C; end
如果我看到上面的代码,希望以后能够实例化C:
C.new
但是,假设 C 已经被定义为一个模块:
# In one file:
module C; end
# Later in a different file:
class C; end # C is actually a module
C.new # fails
Ruby 在 C 被重新定义为 class 的地方出现了问题(C 的定义冲突),而不是让程序继续到使用 C 的地方。
尽早发现问题的好处通常是越早发现错误,就越容易找到并修复其根本原因(在这个例子中,也许 C 应该是 class所有,因此真正的问题是 module C
定义)。
你的第二个问题是,我认为,为什么 class 不能 always 用作模块,例如为什么禁止以下内容:
class C; end
class A
include C
end
我认为,答案是编程语言以 概念 开始,然后使用各种构造 实现 。我们可以描述 classes 和模块如下:
- A class 表示具有数据和行为的对象(classic OOP 定义)。
- 模块是行为的集合。
include
关键字使用模块的 行为 扩展了 class。原则上,可以只采用 class 的方法并将它们添加到另一个 class。但是这个操作没有意义因为class是一个对象和它的行为在一起。只采取行为违背了 class.
还有其他编程语言在这个问题上采取不同的立场。例如,在 JavaScript 中,任何函数都可以从任何 class 中取出,并使用任何其他 class 的实例调用。这在某些情况下很方便,但在其他情况下却很难调试。