在Ruby中模拟抽象类(Rails)

d13*_*r43 2 ruby ruby-on-rails ruby-on-rails-3

我想在Ruby on Rails中模拟一个抽象类.即如果有人试图打电话我想提出异常Abstract.new,但他应该可以打电话Child.new(同时Child < Abstract).

这该怎么做?覆盖两者newinitialize不起作用.

Way*_*rad 11

在另一条评论中,OP提到抽象类的目的是分享其子代所需的行为(方法).在Ruby中,通常最好使用一个模块,用于在需要时"混合"方法.例如,而不是:

class Abstract
  def foo
    puts "foo!"
  end
end

class Concrete
end

Concrete.new.foo # => "foo!"
Run Code Online (Sandbox Code Playgroud)

这个:

module Foo
  def foo
    puts "foo!"
  end
end

class Concrete
  include Foo
end

Concrete.new.foo # => "foo!"
Run Code Online (Sandbox Code Playgroud)

但这是原始请求可能如何满足:

#!/usr/bin/ruby1.8

class Abstract

  def initialize(*args)
    raise if self.class == Abstract
    super
  end

end

class Concrete < Abstract
end

Concrete.new # OK
Abstract.new # Raises an exception
Run Code Online (Sandbox Code Playgroud)


Jak*_*tad 7

你为什么想做这个?抽象/接口类的要点是将强类型语言破解成动态范例.如果你需要你的类适合签名,根据原始类命名你的方法或制作一个外观并插入它,不需要欺骗编译器允许它,它只是工作.

def my_printer obj
  p obj.name
end
Run Code Online (Sandbox Code Playgroud)

所以我将接口定义为具有name属性的任何对象

class person
  attr_accessor :name
  def initialize
   @name = "Person"
  end
end

class Employee
   attr_accessor :name
  def initialize
   @name = "Employee"
   @wage = 23
  end
end
Run Code Online (Sandbox Code Playgroud)

所以没有什么能阻止我们用这两种方法调用我们的打印机方法

my_printer Person.new
my_printer Employee.new
Run Code Online (Sandbox Code Playgroud)

两者都打印出来,没有任何障碍:D

  • 基本上,这是一个评论,而不是答案. (12认同)
  • 在Ruby中,类的*only*点是可以实例化的.使用一种语言结构,其唯一的存在理由是实例化,然后询问如何使其无法实例化,这是没有意义的.所以,这不仅是一个答案,而且是一个非常好的答案.+1. (3认同)