https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112012-05-23T00:03:10ZRuby Issue Tracking SystemRuby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=267622012-05-23T00:03:10Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Feedback</i></li></ul><p>I don't understand you.</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=267632012-05-23T00:12:30Ztrans (Thomas Sawyer)
<ul></ul><p>=begin<br>
Sorry, I'll be more specific via example:</p>
<p>class Foo < BasicObject<br>
end</p>
<p>foo = Foo.new</p>
<p>foo.class #=> raises NoMethodError</p>
<p>How to get class?</p>
<p>I suggest adding #<strong>class</strong> feature if there is no current means.<br>
=end</p> Ruby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=267642012-05-23T00:20:02Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Feedback</i> to <i>Assigned</i></li><li><strong>Assignee</strong> set to <i>matz (Yukihiro Matsumoto)</i></li></ul><p>Okay, thanks. I assign this to matz.</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=267782012-05-23T14:17:49Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Feedback</i></li><li><strong>Target version</strong> changed from <i>1.9.3</i> to <i>2.0.0</i></li></ul><p>=begin<br>
((<em>Why</em>)) do you need it?</p>
<p>BTW, it's possible with pure-ruby.</p>
<p>class Foo < BasicObject<br>
include ::Kernel.dup.module_eval {<br>
alias_method(:<strong>class</strong>, :class)<br>
undef_method *(instance_methods - [:<strong>class</strong>, :object_id])<br>
self<br>
}<br>
end</p>
<p>p Foo.new.<strong>class</strong><br>
=end</p> Ruby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=267792012-05-23T14:34:51Ztrans (Thomas Sawyer)
<ul></ul><p>=begin<br>
To ensure proper functionality when creating new instances from subclasses.</p>
<p>class Foo < BasicObject<br>
def initialize(stuff)<br>
@stuff = stuff<br>
end<br>
def dup<br>
<strong>class</strong>.new(@stuff)<br>
end<br>
end</p>
<p>class Bar < Foo<br>
end</p>
<p>We can't use (({Foo})) in dup, otherwise Bar would not be right.<br>
=end</p> Ruby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=267802012-05-23T14:38:09Ztrans (Thomas Sawyer)
<ul></ul><blockquote>
<p>"BTW, it's possible with pure-ruby."</p>
</blockquote>
<p>That's a rather nasty implementation. Is there no better way than that? I tried binding Kernel method but that didn't work, obviously, b/c BasicObject isn't "an instance of Kernel".</p> Ruby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=267902012-05-24T14:56:13Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p>=begin<br>
Seems what you want is (({dup})), not (({<strong>class</strong>})).</p>
<p>class Foo < BasicObject<br>
mix ::Kernel, dup: :dup, clone: :clone<br>
end<br>
=end</p> Ruby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=267952012-05-24T20:10:44Ztrans (Thomas Sawyer)
<ul></ul><p>That was just one example. Here, you can look at this for more cases:</p>
<p><a href="https://github.com/rubyworks/ostruct2/blob/master/lib/ostruct2.rb" class="external">https://github.com/rubyworks/ostruct2/blob/master/lib/ostruct2.rb</a></p>
<p>Just ctrl-f for <strong>class</strong>.</p>
<p>But what's this about "mix"? What Ruby are you running!? This is interesting, b/c I was thinking that I could use <code>#respond_to?</code> and I don't see anyway to add it to my BasicObject subclass except the "nasty" approach you demonstrated earlier.</p> Ruby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=268032012-05-25T01:14:32Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p>=begin<br>
(({Module#mix})) is a feature introduced last year, but may be removed from 2.0.<br>
=end</p> Ruby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=268052012-05-25T04:01:00ZEregon (Benoit Daloze)
<ul></ul><p>nobu (Nobuyoshi Nakada) wrote:</p>
<blockquote>
<p>Seems what you want is (({dup})), not (({<strong>class</strong>})).</p>
<p>class Foo < BasicObject<br>
mix ::Kernel, dup: :dup, clone: :clone<br>
end</p>
</blockquote>
<p>But that would include all methods from Kernel with the current behavior of #mix, as <code>mix ::Kernel</code> would do.<br>
So you need to opt-out all methods:</p>
<pre><code>class Foo < BasicObject
meths = (::Kernel.instance_methods - [:dup])
mix ::Kernel, meths.each_with_object(dup: :dup) { |m,h| h[m] = nil }
end
</code></pre>
<p>(And Foo.new.dup fails with "undefined method `initialize_dup'")</p>
<p>That behavior of #mix is not very intuitive I think, what do you think about:</p>
<p>diff --git a/class.c b/class.c<br>
index 8e637c0..e9d7a7e 100644<br>
--- a/class.c<br>
+++ b/class.c<br>
@@ -769,8 +769,9 @@ do_mix_method_i(st_data_t key, st_data_t value, st_data_t arg)<br>
st_table *aliasing = argp->aliasing;<br>
st_data_t old, alias;</p>
<ul>
<li>if (aliasing && st_lookup(aliasing, ID2SYM(id), &alias)) {</li>
<li>
<pre><code> if (NIL_P(alias)) return ST_CONTINUE;
</code></pre>
</li>
</ul>
<ul>
<li>if (aliasing) {</li>
<li>
<pre><code> if (!st_lookup(aliasing, ID2SYM(id), &alias) || NIL_P(alias))
</code></pre>
</li>
<li>
<pre><code> return ST_CONTINUE;
id = rb_to_id(alias);
</code></pre>
}<br>
if (st_lookup(argp->mtbl, id, &old)) {</li>
</ul>
<p>(and corresponding changes for the three other functions).<br>
That is, if a Hash of methods is given, only import these methods.</p> Ruby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=315652012-10-25T21:34:25Zyhara (Yutaka HARA)
<ul><li><strong>Target version</strong> changed from <i>2.0.0</i> to <i>2.6</i></li></ul> Ruby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=315932012-10-26T12:10:17Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p>=begin<br>
"Method transplanting" is introduced into 2.0, so you can write:<br>
class Foo < BasicObject<br>
include ::Module.new {<br>
[:dup, :initialize_dup, :initialize_copy].each {|m|<br>
define_method(m, ::Kernel.instance_method(m))<br>
}<br>
}<br>
end</p>
<p>I expect someone would make such method in (({Module})) as an external library.<br>
=end</p> Ruby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=327532012-11-11T00:21:44Zalexeymuranov (Alexey Muranov)
<ul></ul><p>Maybe <code>BasicObject</code> is not intended to be subclassed directly? Why not to subclass <code>Object</code> instead? I do not think it is wrong that basic objects do not know who their class is, after all they are basic.</p> Ruby master - Feature #6478: BasicObject#__class__https://redmine.ruby-lang.org/issues/6478?journal_id=687852017-12-25T18:15:05Znaruse (Yui NARUSE)naruse@airemix.jp
<ul><li><strong>Target version</strong> deleted (<del><i>2.6</i></del>)</li></ul>