Ruby YARD:记录抽象方法实现

我有一个典型的OO模式:一个基本抽象类(定义抽象方法)和几个以类特定方式实现这些抽象方法的类.

我习惯在抽象方法中只编写一次文档然后自动传播到几个具体的类(至少它在Javadoc中,在Scaladoc中,在Doxygen中以下面的方式工作),即我不需要重复相同的描述在所有具体课程中.

但是,我无法找到如何在YARD中进行此类传播.我试过,例如:

# Some description of abstract class.
# @abstract
class AbstractClass
  # Some method description.
  # @return [Symbol] some return description
  # @abstract
  def do_something
    raise AbstractMethodException.new
  end
end

class ConcreteClass < AbstractClass
  def do_something
    puts "Real implementation here"
    return :foo
  end
end

我得到了什么:

>代码按预期工作 – 即抛出AbstractMethodException在抽象类中调用,在具体类中完成工作
>在YARD中,AbstractClass明确定义为抽象,ConcreteClass是正常的
> AbstractClass中的方法描述和返回类型都很好
> Method说在AbstractClass中抛出AbstractMethodException
> Method在ConcreteClass中根本没有描述和泛型Object返回类型,没有一个通知表明基类中存在抽象方法.

我期望得到什么:

> Method的描述和返回类型从AbstractClass的info继承(即复制)到ConcreteClass
>理想情况下,此方法在ConcreteClass描述的“继承”或“已实现”部分中指定,具有从ConcreteClass#do_something到AbstractMethod#do_something的一些参考链接.

有可能这样做吗?

解决方法

我认为这个问题归结为你要做的事情.看起来你正在尝试在Ruby中实现一个接口,如果你来自Java或.NET,这是有意义的,但实际上并不是Ruby开发人员的工作方式.

以下是关于Ruby中接口的典型思想的一些信息:What is java interface equivalent in Ruby?

那就是说,我明白你要做什么.如果您不希望直接实现AbstractClass,但是您想要定义可以在类似AbstractClass规定的类中使用的方法(如Design by Contract),那么您可能希望使用模块.模块可以很好地保存代码DRY,但是它们并没有完全解决与记录overridden methods相关的问题.所以,在这一点上,我认为你可以重新考虑如何处理文档,或者至少在更多Ruby-ith中处理它办法.

Ruby中的继承(实际上根据我自己的经验)仅用于以下几个原因:

>可重用的代码属性
>认行为
>专业化

显然还有其他边缘情况,但老实说这就是Ruby中常用的继承.这并不意味着你正在做的事情不起作用或违反某些规则,它在Ruby(或大多数动态类型语言)中并不常见.这种非典型行为可能是YARD(和其他Ruby doc生成器)没有达到预期效果的原因.也就是说,创建一个只定义子类中必须存在的方法的抽象类,从代码的角度来看,实际上只能获得很少的收益.未定义的方法将导致无论如何抛出NoMethodError异常,并且您可以使用#respond_to?(:some_method)以编程方式检查对象是否将从方法调用方法调用(或任何消息)响应该方法.或其他用于获取元素的反射工具).这一切都归功于Ruby对Duck Typing的使用.

对于纯文档,为什么要记录一个实际上没有使用的方法?您不应该真正关心通过调用方法发送或接收的对象的类,只是这些对象响应的内容.因此,如果在这里没有添加任何实际值,请不要首先创建您的AbstractClass.如果它包含您实际将直接调用方法而不覆盖,则创建一个Module,在那里记录它们,并运行$yardoc –embed-mixins以包含在混合模块中定义的方法(及其描述).否则,记录实际实现它们的方法,因为每个实现应该是不同的(否则为什么要重新实现它).

以下是我与你正在做的事情类似的事情:

# An awesome Module chock-full of reusable code
module Stuff
  # A powerful method for doing things with stuff,mostly turning stuff into a Symbol
  def do_stuff(thing)
    if thing.kind_of?(String)
      return thing.to_sym
    else
      return thing.to_s.to_sym
    end
  end
end

# Some description of the class
class ConcreteClass
  include Stuff

  # real (and only implementation)
  def do_something
    puts "Real implementation here"
    return :foo
  end
end

an_instance = ConcreteClass.new
an_instance.do_somthing       # => :foo
# > Real implementation here
an_instance.do_stuff("bar")   # => :bar

运行YARD(使用–embed-mixins)将包括Stuff模块中混入的方法(及其描述),您现在知道包括Stuff模块在内的任何对象都将具有您期望的方法.

您可能还想查看Ruby Contracts,因为它可能更接近您正在寻找的绝对强制方法接受并仅返回您想要的对象类型,但我不确定如何与YARD一起使用.

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...