简体   繁体   English

设计Ruby API时的类与模块?

[英]Class vs Module in designing Ruby API?

When I read more about Ruby metaprogramming, most of the time we found at least two solutions to solve a problem. 当我阅读有关Ruby元编程的更多信息时,大多数时候我们发现至少有两种解决方案来解决问题。 Please look at two examples below: 请看下面两个例子:

class Base
  def self.has_many(*args)
    # ...
  end
end

class Student < Base
  has_many :books
end

Another style: 另一种风格:

module Base
  def self.included(klass)
    klass.extend ClassMethods
  end

  module ClassMethods
    def has_many(*args)
      # ...
    end
  end
end

class Student
  include Base

  has_many :books
end

But when we design api, we have to decide which one to use, but I would like to ask your ideas and some of best practices that most people have already implemented in their libraries. 但是当我们设计api时,我们必须决定使用哪一个,但我想问一下大多数人已经在他们的库中实现的想法和一些最佳实践。

If your API is providing the base functionality which will be extended by the client, then you should prefer inheritance . 如果您的API提供了将由客户端扩展的基本功能,那么您应该更喜欢继承

If your API is going to extend various clients with their own base functionality, then you should go for composition . 如果您的API将使用自己的基本功能扩展各种客户端,那么您应该进行合成

You've got a lot of theories around that question. 你有很多围绕这个问题的理论。

I tend to prefer composition because it makes behavior a lot more reusable that way but if you look at Rails, you'll have to subclass ActiveRecord::Base class every time you want to an object in your database. 我倾向于喜欢组合,因为它使行为更加可重用,但是如果你看看Rails,每次你想要数据库中的对象时,你都必须继承ActiveRecord :: Base类。 If you look at DataMapper, it's the opposite as they just required you to include DataMapper::Resource. 如果你看一下DataMapper,它就是相反的,因为它们只需要你包含DataMapper :: Resource。

Inheritance vs Composition (via modules) is a big topic and the question you'll have to ask yourself will come down to: how can I achieve the greater decoupling between the components I provide and another user existing code base? 继承与组合(通过模块)是一个很大的主题,您必须问自己的问题将归结为:如何实现我提供的组件与另一个用户现有代码库之间更大的解耦?

Ruby supports single inheritance only. Ruby仅支持单继承。 Therefore if API client must inherit your base class, they lose the ability to inherit other classes. 因此,如果API客户端必须继承您的基类,则它们将无法继承其他类。 Using module inclusion you make possible a code like: 使用模块包含,您可以使代码如下:

class Student < Person
  include Base
  has_many :books
end

And thus you can "inherit" both Person and Base. 因此,您可以“继承”Person和Base。

However, classical inheritance syntax looks more natural and less "magic" 但是,经典的继承语法看起来更自然,更少“神奇”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM