在实例化时将类转换为子类
我正在编写一个用于查询 Mediawiki API 的框架。我有一个 Page
类,它代表 wiki 上的文章,我还有一个 Category
类,它是一个 Page
具有更具体的方法(例如能够计算类别中的成员数量。我还有一个方法 Page#category?
,它确定实例化的 Page 是否
对象实际上代表一个 Mediawiki 类别页面,通过查询 API 来确定文章的命名空间,
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
我想要做的是能够检测我的框架的用户是否尝试使用实例化 Mediawiki 类别。 Page 对象(即 Page.new("Category:My Category")
),如果是,则实例化一个 Category
对象,而不是 Page< /code> 对象,直接来自
Page
构造函数
在我看来这应该是可能的,因为它让人想起 Rails 中的单表继承,但我不知道如何去实现它。工作。
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
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.
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好的,有几件事:
您无法将类
A
的实例转换为A
的子类B 的实例
。至少,不会自动发生。B
可以(通常确实)包含A
中不存在的属性,它可以具有完全不同的构造函数等。因此,据我所知,没有任何 OO 语言将允许您“转换”就这样上课。即使在静态类型语言中,当您实例化
B
,然后将其分配给A
类型的变量a
时,它仍然是B
,它不会转换为其祖先类。Ruby 是一种动态语言,具有强大的反射功能,因此您始终可以决定在运行时实例化哪个类 - 检查一下:
因此,这里不需要任何转换 - 只需首先实例化您需要的类即可。
另一件事:正如我在评论中提到的,方法
category?
完全是错误的,因为它违反了 OOP 原则。在 Ruby 中,您可以而且应该使用方法is_a?
,因此您的检查将如下所示:这只是冰山一角,还有更多关于实例化不同类的信息,以及我的另一个问题评论中的链接可能是一个很好的起点,尽管其中的一些代码示例可能会让您感到困惑。但理解它们绝对是值得的。
编辑:重新阅读您更新的问题后,在我看来,您的正确方法是创建一个工厂类并让它检测和实例化不同的页面类型。因此,用户不会直接调用
Page.new
,而是调用类似get_page
方法来实例化相应的类。Ok, couple of things:
You can't convert an instance of a class
A
to an instance ofA
's subclassB
. At least, not automatically.B
can (and usually does) contain attributes not present inA
, it can have completely different constructor etc. So, AFAIK, no OO language will allow you to "convert" classes that way.Even in static-typed languages, when you instantiate
B
, and then assign it to a variablea
of typeA
, it is still instance ofB
, it is not converted to its ancestor class whatsoever.Ruby is a dynamic language with powerful reflection capabilities, so you can always decide which class to instantiate in the runtime - check this out:
So, no need for any conversion here - just instantiate the class you need in the first place.
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 methodis_a?
, so your check will look like: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.
Edit: 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 likeand
get_page
method would instantiate corresponding class.为什么不做这样的事情呢?能够做到这一点,就已经是一个足够好的理由了!
Why not something like this? Being able to do that is a good enough reason to do it!
您可以定义一个方法来实例化该类并返回实例。
这被称为工厂模式
You could define a method that instantiate the class and returns the instance.
This is know as Factory Pattern