3

Mediawiki APIを照会するためのフレームワークを作成しています。私はPageウィキの記事を表すクラスを持っています。またより具体的なメソッド (カテゴリ内のメンバーの数を数えることができるなど) を持つCategoryクラスも持っています。インスタンス化されたオブジェクトが実際に Mediawiki カテゴリ ページを表しているかどうかを判断するには、API にクエリを実行して記事の名前空間を判断します。 PagePage#category?Page

class Page
  def initialize(title)
    # do initialization stuff
  end

  def category?
    # query the API to get the namespace of the page and then...
    namespace == CATEGORY_NAMESPACE
  end
end

class Category < Page
  # ...
end

私がやりたいことは、フレームワークのユーザーが Page オブジェクト (つまり ) を使用して Mediawiki カテゴリをインスタンス化しようとしているかどうかを検出できるようにすることです。そうであれば、コンストラクターから直接、オブジェクトではなくオブジェクトをPage.new("Category:My Category")インスタンス化します。CategoryPagePage

Rails の単一テーブルの継承を連想させるので、これは可能であるように思えますが、それを機能させる方法がわかりません。

4

3 に答える 3

6

わかりました、いくつかのこと:

クラスのインスタンスをのサブクラスのインスタンスに変換することはできません。少なくとも、自動的ではありません。に存在しない属性を含むことができます(通常は含みます)、完全に異なるコンストラクターなどを持つことができます。したがって、AFAIK、オブジェクト指向言語ではクラスをそのように「変換」できません。AABBA

静的型付け言語でも、 をインスタンス化し、それを typeBの変数に代入すると、それは依然として のインスタンスであり、祖先クラスにはまったく変換されません。aAB

Ruby は強力なリフレクション機能を備えた動的言語であるため、ランタイムでインスタンス化するクラスをいつでも決定できます。これを確認してください。

puts "Which class to instantiate: "
class_name = gets.chomp
klass = Module.const_get class_name
instance = klass.new

したがって、ここで変換する必要はありません。最初に必要なクラスをインスタンス化するだけです。

別のこと: コメントで述べたように、category?OOP の原則に違反しているため、メソッドは単に間違っています。Ruby では、 methodis_a?を使用できます (使用する必要があります)。そのため、チェックは次のようになります。

if instance.is_a? Category
  puts 'Yes, yes, it is a category!'
else
  puts "Nope, it's something else."
end

これは氷山の一角にすぎません。さまざまなクラスのインスタンス化については他にもたくさんあります。コメントでリンクした別の質問は、出発点として最適ですが、そこにあるいくつかのコード例は混乱を招く可能性があります。しかし、それらを理解することは間違いなく価値があります。

編集:更新された質問を読み直した後、ファクトリ クラスを作成し、さまざまなページ タイプの検出とインスタンス化を行うことが正しい方法であるように思われます。したがって、ユーザーはPage.new直接呼び出すのではなく、次のようなものを呼び出します

MediaWikiClient.get_page "Category:My Category"

get_pageメソッドは、対応するクラスをインスタンス化します。

于 2010-07-31T07:24:36.467 に答える
3

なぜこのようなものではないのですか?それができるということは、それを行う十分な理由です!

class Page
  def self.new(title)
    if self == Page and is_category?(title)
      Category.new(title)
    else
      super
    end
  end

  def self.is_category?(title)
    # ... (query the API etc.)
  end

  def initialize(title)
    # do initialization stuff
  end

  def category?
    # query the API to get the namespace of the page and then...
    namespace == CATEGORY_NAMESPACE
  end
end

class Category < Page
  # ...
end
于 2012-04-28T00:39:02.187 に答える
1

クラスをインスタンス化してインスタンスを返すメソッドを定義できます。これは工場パターンとして知られています

class PageFactory
  def create(title) # the pattern uses "create".. but "new" is more Ruby' style
    namespace = title[/\A[^:]+(?=:)/]
     # matches the prefix, up to and excluding the first colon.
    if namespace == CATEGORY_NAMESPACE
      Category.new(title)
    else
      Page.new(title)
    end
  end
end

class ClientClass
  def do_something()
    factory = PageFactory.new
    my_page = factory.create('Category:Foo') 
    my_page.do_something()
  end
end

于 2010-07-31T04:57:09.853 に答える