0

APIのネットワークを強化するライブラリを作成中です。そのライブラリの中心は現在、各APIクライアントがサブクラス化するClientクラスです。私はすべてのAPIを作成しているので、すべて同じように機能します(RESTful、access_tokenによる承認など)。

ただし、他のruby APIクライアントライブラリ(Twitterなど)とは異なり、クライアントクラスを直接インスタンス化しないでください。これは、ライブラリが単一のAPIに制限されていないためです。代わりに、各APIクライアントはClientクラスをサブクラス化します。私の質問は次のとおりです。

Rubyクラスがサブクラスを介してのみ初期化されることを要求する方法はありますか?

さらに、この質問を読んで、ここでのミックスインよりもクラスの方が優れていると判断しました。

コードが必要な人のために、ここに例があります:

class A
    def initialize(options = {})
        #what goes on in here doesn't really matter for the purpose of this question
        #I just don't want it to be initialized directly
        options.each do |k,v|
            instance_variable_set("@#{k}",v) unless v.nil?
        end
    end
end

class B < A
    attr_accessor :class_specific_opt
    def initialize( options = {} )
        @class_specific_opt = "val" unless options[:class_specific_opt].nil?
        super(options)
    end
end

何かご意見は?

4

5 に答える 5

2

抽象のようなクラスに関する答えがここにあります:rubyで抽象クラスを実装する方法は?、Aをモジュールとして提供し、その実装者に含める方がよい場合もあります。

于 2012-11-26T17:56:37.953 に答える
2

あなたはこのようなことをすることができます:

class A
  def self.initialize_allowed?
    raise "You cannot initialize instances of this class."
  end

  def self.allow_initialize
    class << self
      def initialize_allowed?
        true
      end
    end
  end

  def initialize(options = {})
    self.class.initialize_allowed?
    options.each do |k,v|
      instance_variable_set("@#{k}", v)
    end
  end
end

呼び出すA.newとRuntimeErrorが発生し、initializeメソッドが停止します。initialized_allowed?次に、サブクラスを呼び出すことにより、サブクラスのメソッドをオーバーライドできますallow initialize。(多分これはやり過ぎですが、私allow_initializeはより読みやすいと思いますdef self.initialize_allowed?;end):

class B < A
  allow_initialize
end

B.new #=> #<B:0x00000102837d10>
于 2012-11-26T18:49:24.763 に答える
1

A.new呼び出されたくない場合は、次のようにします。

class <<A
  undef :new
end

そうすると、それを呼び出すことができなくなります。

A.new #=> NoMethodError: undefined method `new' for A:Class
于 2012-11-26T19:07:10.287 に答える
0

追加

private_class_method :new

クラスAに、そして

public_class_method :new

クラスBに。

于 2012-11-26T19:15:15.253 に答える
0

新しい方法を作るのが最善の方法だと思いますprivate。これはまさにrubySingletonモジュールが行うことです。シングルトンモジュールのドキュメント

class A
  private_class_method :new
end

class B < A
  public_class_method :new
end
于 2012-11-26T19:19:40.600 に答える