Ruby 如何创建没有';新';方法?
我想要一个不支持通过Ruby 如何创建没有';新';方法?,ruby,Ruby,我想要一个不支持通过new实例化的类,比如Integer类。我尝试从BasicObject继承,但它仍然允许我使用new创建一个实例。您有几个选项,我将在这里(粗略地)按我个人认为它们的“攻击性”的顺序介绍: 用您自己的文件覆盖默认的对象#初始化 您可以使用自己的执行不同操作的实现覆盖Object#initialize的默认实现。在您的情况下,例如: 的默认实现将自动调用您的Foo#initialize实现,然后引发异常并中止对象构造,或者更准确地说:它将中止对象初始化,由于对象将在调用init
new
实例化的类,比如Integer
类。我尝试从BasicObject
继承,但它仍然允许我使用new
创建一个实例。您有几个选项,我将在这里(粗略地)按我个人认为它们的“攻击性”的顺序介绍:
用您自己的文件覆盖默认的对象#初始化
您可以使用自己的执行不同操作的实现覆盖Object#initialize
的默认实现。在您的情况下,例如:
的默认实现将自动调用您的Foo#initialize
实现,然后引发异常
并中止对象构造,或者更准确地说:它将中止对象初始化,由于对象将在调用initialize
时构造(否则,如果没有可调用的对象,您将如何调用initialize
),但是,对象构造成本很低,并且对象将立即符合垃圾收集的条件,因此这不重要
为完整起见,以下是Class#new
的默认实现(大致)的样子:
class Class
def new(*args, &b)
obj = allocate
obj.send(:initialize, *args, &b) # `initialize` is `private`, must use `send`
obj
end
end
如您所见,在调用initialize
时,将已经构建了对象
用自己的代码覆盖默认的类#new
您可以使用自己的实现覆盖Class#new
的默认实现,该实现会做一些不同的事情。在您的情况下,例如,引发异常
:
def Foo.new(*) raise TypeError, "`#{self}` cannot be instantiated." end
Foo.new
# TypeError: `Foo` cannot be instantiated.
# from (…):3:in `new'
使Foo::new
aprivate
方法
您可以将Foo
a的singleton类的new
方法设置为,这样,它就不能用显式接收器调用:
Foo.private_class_method :new
Foo.new
# NoMethodError: private method `new' called for Foo:Class
# from (…):3:in `…'
例如,这仍然允许您使用特殊的工厂方法来构造类的实例,例如:
def Foo.create_from_xml(file)
# do stuff to parse `file`
new(argument_parsed_from_file)
end
请注意模块#专用类(class)方法
文档中的这句话:
通常用于隐藏默认构造函数new
下面是代码示例
从Foo的singleton类中取消定义new
方法
您可以使用取消定义新的
方法undef_method
将阻止模块实例完全响应该消息,而不是从模块中删除该方法,因此方法查找通常会在继承链上继续进行
Foo.singleton_class.undef_method :new
Foo.new
# NoMethodError: undefined method `new' for Foo:Class
# from (…):3:in `…'
你有几个选择,我将在这里(大致)按照我个人观点中的“攻击性”顺序介绍:
用您自己的文件覆盖默认的对象#初始化
您可以使用自己的执行不同操作的实现覆盖Object#initialize
的默认实现。在您的情况下,例如:
的默认实现将自动调用您的Foo#initialize
实现,然后引发异常
并中止对象构造,或者更准确地说:它将中止对象初始化,由于对象将在调用initialize
时构造(否则,如果没有可调用的对象,您将如何调用initialize
),但是,对象构造成本很低,并且对象将立即符合垃圾收集的条件,因此这不重要
为完整起见,以下是Class#new
的默认实现(大致)的样子:
class Class
def new(*args, &b)
obj = allocate
obj.send(:initialize, *args, &b) # `initialize` is `private`, must use `send`
obj
end
end
如您所见,在调用initialize
时,将已经构建了对象
用自己的代码覆盖默认的类#new
您可以使用自己的实现覆盖Class#new
的默认实现,该实现会做一些不同的事情。在您的情况下,例如,引发异常
:
def Foo.new(*) raise TypeError, "`#{self}` cannot be instantiated." end
Foo.new
# TypeError: `Foo` cannot be instantiated.
# from (…):3:in `new'
使Foo::new
aprivate
方法
您可以将Foo
a的singleton类的new
方法设置为,这样,它就不能用显式接收器调用:
Foo.private_class_method :new
Foo.new
# NoMethodError: private method `new' called for Foo:Class
# from (…):3:in `…'
例如,这仍然允许您使用特殊的工厂方法来构造类的实例,例如:
def Foo.create_from_xml(file)
# do stuff to parse `file`
new(argument_parsed_from_file)
end
请注意模块#专用类(class)方法
文档中的这句话:
通常用于隐藏默认构造函数new
下面是代码示例
从Foo的singleton类中取消定义new
方法
您可以使用取消定义新的
方法undef_method
将阻止模块实例完全响应该消息,而不是从模块中删除该方法,因此方法查找通常会在继承链上继续进行
Foo.singleton_class.undef_method :new
Foo.new
# NoMethodError: undefined method `new' for Foo:Class
# from (…):3:in `…'
这个怎么样
module MyClassWithOnlyClassMethods
extend self
def foo
end
end
实际上,您可以在不使用扩展self
的情况下执行此操作,但是您必须为每个方法编写def self.foo
等,这会变得很麻烦。这样如何
module MyClassWithOnlyClassMethods
extend self
def foo
end
end
实际上,您可以在不使用扩展self
的情况下完成,但是您必须为每个方法编写def self.foo
等,这会变得很麻烦。如果不使用new
,您将如何创建实例?如果我想使所有方法都成为类方法,该怎么办?这个问题是理论性的,我想知道没有新类的标准类是如何实现的如果你不需要类的实例,那么它就不是一个类,而是一个模块。Integer(可能还有其他一些基本类型)在这方面是一个特殊的类:它不是一个包含state和all的“real”类。也就是说,这可以通过使用来实现。如果您想禁用实例化inst的选项,我会提出异议