Chi*_*tan 113 ruby abstract-class
我知道ruby中没有抽象类的概念.但是,如果它需要实施,那该怎么办呢?我试过像......
class A
def self.new
raise 'Doh! You are trying to write Java in Ruby!'
end
end
class B < A
...
...
end
Run Code Online (Sandbox Code Playgroud)
但是当我尝试实例化B时,它会在内部调用A.new
哪个会引发异常.
此外,模块无法实例化,但也无法继承.使新方法私有也行不通.有什么指针吗?
Dan*_*ark 111
只是为了在这里编写,我认为没有理由阻止某人实例化抽象类,特别是因为他们可以动态添加方法.
鸭子类型语言(如Ruby)在运行时使用方法的存在/不存在或行为来确定是否应该调用它们.因此,您的问题,因为它适用于抽象方法,是有道理的
def get_db_name
raise 'this method should be overriden and return the db name'
end
Run Code Online (Sandbox Code Playgroud)
这应该是关于故事的结尾.在Java中使用抽象类的唯一原因是坚持某些方法被"填充",而其他方法则在抽象类中使用它们的行为.在鸭子打字语言中,重点是方法,而不是类/类型,所以你应该把你的担忧转移到那个级别.
在你的问题中,你基本上是在尝试abstract
从Java 重新创建关键字,这是在Ruby中编写Java的代码味道.
nak*_*ima 57
我不喜欢在Ruby中使用抽象类(几乎总是有更好的方法).如果你真的认为它是最适合这种情况的技术,你可以使用下面的代码片段来更多地声明哪些方法是抽象的:
module Abstract
def abstract_methods(*args)
args.each do |name|
class_eval(<<-END, __FILE__, __LINE__)
def #{name}(*args)
raise NotImplementedError.new("You must implement #{name}.")
end
END
# important that this END is capitalized, since it marks the end of <<-END
end
end
end
require 'rubygems'
require 'rspec'
describe "abstract methods" do
before(:each) do
@klass = Class.new do
extend Abstract
abstract_methods :foo, :bar
end
end
it "raises NoMethodError" do
proc {
@klass.new.foo
}.should raise_error(NoMethodError)
end
it "can be overridden" do
subclass = Class.new(@klass) do
def foo
:overridden
end
end
subclass.new.foo.should == :overridden
end
end
Run Code Online (Sandbox Code Playgroud)
基本上,您只需abstract_methods
使用抽象方法列表调用,当它们被抽象类的实例调用时,NotImplementedError
将引发异常.
And*_*ers 43
试试这个:
class A
def initialize
raise 'Doh! You are trying to instantiate an abstract class!'
end
end
class B < A
def initialize
end
end
Run Code Online (Sandbox Code Playgroud)
blu*_*ana 14
class A
private_class_method :new
end
class B < A
public_class_method :new
end
Run Code Online (Sandbox Code Playgroud)
小智 12
我的2¢:我选择简单轻巧的DSL mixin:
module Abstract
extend ActiveSupport::Concern
included do
# Interface for declaratively indicating that one or more methods are to be
# treated as abstract methods, only to be implemented in child classes.
#
# Arguments:
# - methods (Symbol or Array) list of method names to be treated as
# abstract base methods
#
def self.abstract_methods(*methods)
methods.each do |method_name|
define_method method_name do
raise NotImplementedError, 'This is an abstract base method. Implement in your subclass.'
end
end
end
end
end
# Usage:
class AbstractBaseWidget
include Abstract
abstract_methods :widgetify
end
class SpecialWidget < AbstractBaseWidget
end
SpecialWidget.new.widgetify # <= raises NotImplementedError
Run Code Online (Sandbox Code Playgroud)
当然,在这种情况下,为初始化基类添加另一个错误将是微不足道的.
Fre*_*ore 12
对于rails世界中的任何人来说,在模型文件中使用此声明来实现ActiveRecord模型作为抽象类:
self.abstract_class = true
Run Code Online (Sandbox Code Playgroud)
Aus*_*ler 10
在编程Ruby的最后6年半里,我不需要一次抽象类.
如果您认为自己需要一个抽象类,那么您在提供/需要它的语言中会考虑太多,而不是在Ruby中.
正如其他人所建议的那样,mixin更适合于那些应该是接口的东西(正如Java定义的那样),重新思考你的设计更适合那些需要来自其他语言(如C++)的抽象类的东西.
更新2019:在使用16年半的时间里,我不需要Ruby中的抽象类.通过实际学习Ruby并使用适当的工具(如模块(甚至可以为您提供常见实现)),可以解决所有人对我的回复所做的评论.我管理的团队中有些人创建了基本实现失败的类(如抽象类),但这些人大多浪费编码,因为它NoMethodError
会产生与生产中完全相同的结果AbstractClassError
.
归档时间: |
|
查看次数: |
85690 次 |
最近记录: |