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
a
private
方法 您可以将
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
a
private
方法 您可以将
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的选项,我会提出异议