在实例化时将类转换为子类 [英] Convert a class to a subclass on instantiation

查看:126
本文介绍了在实例化时将类转换为子类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个用于查询 Mediawiki API 的框架.我有一个Page类,它表示Wiki上的文章,还有一个Category类,该类 -a Page具有更具体的方法(例如能够计数我还获得了方法Page#category?,该方法通过查询API来确定文章的命名空间,从而确定实例化的Page对象是否实际上代表Mediawiki类别页面.

I'm writing a framework for querying the Mediawiki API. I have a Page class which represents articles on the wiki, and I've also got a Category class, which is-a Page with more specific methods (like being able to count the number of members in the category. I've also got a method Page#category? which determines if an instantiated Page object is actually representative of a Mediawiki category page, by querying the API to determine the namespace of the article.

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对象(即Page.new("Category:My Category"))实例化Mediawiki类别,如果是,则实例化Category对象.直接来自Page构造函数的Page对象.

What I would like to do is be able to detect if the user of my framework tries to instantiate a Mediawiki category using a Page object (ie. Page.new("Category:My Category")), and if so, instantiate a Category object, instead of a Page object, directly from the Page constructor.

在我看来这应该可行,因为它让人联想到Rails中的单表继承,但是我不确定如何使它正常工作.

It seems to me that this should be possible because it's reminiscent of single table inheritance in Rails, but I'm not sure how to go about getting it to work.

推荐答案

好,几件事:

您不能将类A的实例转换为A的子类B的实例.至少不是自动的. B可以(并且通常确实)包含A中不存在的属性,它可以具有完全不同的构造函数等.因此,AFAIK,没有OO语言将允许您以这种方式转换"类.

You can't convert an instance of a class A to an instance of A's subclass B. At least, not automatically. B can (and usually does) contain attributes not present in A, it can have completely different constructor etc. So, AFAIK, no OO language will allow you to "convert" classes that way.

即使在静态类型语言中,当实例化B并将其分配给类型A的变量a时,它仍然是B的实例,它不会转换为其祖先类

Even in static-typed languages, when you instantiate B, and then assign it to a variable a of type A, it is still instance of B, it is not converted to its ancestor class whatsoever.

Ruby是一种动态语言,具有强大的反射功能,因此您始终可以决定在运行时实例化哪个类-签出:

Ruby is a dynamic language with powerful reflection capabilities, so you can always decide which class to instantiate in the runtime - check this out:

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

因此,这里不需要任何转换-首先实例化您需要的类.

So, no need for any conversion here - just instantiate the class you need in the first place.

另一件事:正如我在评论中提到的,方法category?完全是错误的,因为它违反了OOP原则.在Ruby中,您可以-并且应该-使用方法is_a?,因此您的检查应类似于:

Another thing: as I mentioned in the comment, method category? is simply wrong, as it violates OOP principles. In Ruby, you can - and should - use method is_a?, so your check will look like:

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

这只是冰山一角,有关实例化不同类的更多信息,尽管注释中的一些代码示例可能会使您感到困惑,但我在注释中链接的另一个问题可能是一个很好的起点.但是绝对值得了解它们.

This is just a tip of the iceberg, there's lot more about instantiating different classes, and another question I have linked in the comment can be a great starting point, although some code examples there might confuse you. But it is definitely worth understanding them.

在重新阅读了更新的问题之后,在我看来,正确的方法是创建一个工厂类,然后让它进行检测和实例化不同的页面类型.因此,用户不会直接调用Page.new,而是会调用类似的

After re-reading your updated question, it seems to me that the right way for you would be to create a factory class and let it do the detecting and instantiating different page types. So, user wouldn't call Page.new directly, but rather call something like

MediaWikiClient.get_page "Category:My Category"

get_page方法将实例化相应的类.

and get_page method would instantiate corresponding class.

这篇关于在实例化时将类转换为子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆