From: gga Date: 2007-02-05T10:10:05+09:00 Subject: Re: Inheriting from Fixnum On 4 feb, 19:33, Robert Klemme wrote: > On 04.02.2007 17:13, gga wrote: > > > > >> I try differently: what kind of class do you want to implement? Why do > >> you think you need to inherit? What capabilities should instances of > >> your class have? > > > Simple. I want a Fixnum. I don't want to pollute Fixnum's namespace > > and I don't want a Fixnum to automatically be promoted to my class, > > while at the same time, my class should be compatible with ALL of > > fixnum methods (odd? even?, etc). > > Think of a Year class (yes, I know there's Date and DateTime -- my > > class is not exactly this but will do as an example). A year is > > represented by a Fixnum, but it is not a Fixnum. > > Yet I expect all Fixnum operations to work on it, returning a new Year > > in case of additions, etc. I also don't want a normal Fixnum to be > > treated as a year without a conversion function or instantiation thru > > Year.new(). Also, I want to have a lof of conversion functions within > > Year that are not applicable to Fixnum ( to_months, to_days, etc ). > > Is it a year of the century or years difference? How would you > implement to_days? I don't think this is worth another class - and btw. > there are classes for date and time handling in Ruby which support all > the math you typically need. Plus, you can also define methods in a > more functional way (i.e. def year_to_months(year) etc.). Robert, I just made an example for you to understand. I'm not quite creating a Year class, albeit I am creating something that is somewhat related ( if you want to know, for video/film work, it is a Frame class, where a frame represents usually represents 1/24 or 1/30 --or 1/ fps- of a second). As such, I do want to have conversion functions that will report the length of time the frames represent but in seconds, minutes, hours, etc. I don't want a Fixnum to be treated as a Frame, as, for example, in the context I'll be using it, negative "frames" make no sense. > > > Right now, to do that, I have to actually recreate all of the methods > > in Fixnum/Numeric/etc. while if I was inheriting from it, I would only > > have to recreate half of them or less or rely on method_missing > > (yuck). > > You can still use delegator... I can (and as I said, I have already), it is just pretty inelegant and inefficient. Taking care of kind_of? and similar is pretty messy (but needed as I do want to have Range of frames, for example). Therefore, I want to know the reason of WHY I am forced to use a delegator for deriving one of the most basic classes possible. So far, I don't know why I need to go through such a cumbersome approach. > > It's an internal optimization. Fixnums do not have to be created and > they never have to be GC'ed. This goes a long way to make math faster > than it would be with ordinary objects (at least for Fixnums). > Very well. It still does not explain much. Why can't I take advantage of this optimization for my own class? As I showed already, Fixnums are also allowed to contain additional data and new methods with them... so I know they are somehow GCed (not the number itself, but any associated data with the Fixnum class). I don't think Ruby is doing *that* much of an optimization if you ask me (ie. every operator always pays the cost of method dispatching). There's obviously a memory optimization of having the Fixnum be represented by VALUE itself (instead of it being a pointer to something else), but not much else, as far as I can tell. Perhaps I should rephrase my question in a simpler manner. Why does the Ruby source code contain an undef() of "new" for Numeric and Floats? Once I understand why those lines in the source code are there, I can then decide whether indeed a delegator is the one and only solution to whatever problem those lines are trying to address. So far, I am seeing it as annoying (and unneeded) limitation. If I remove those lines from the C code, sure enough I can then instantiate a Numeric or an Integer through inheritance, but still not pass a default value to the constructor as the initialize in Integer fails (it seems it defaults to Object's initialize). It seems like if I create my own initialize function in C that sets the FIXNUM flag, but not the IMMEDIATE flag, it should be possible to create an efficient pseudo-int class that you can inherit from normally. I understand some of the dangers of this, but I think it can be done safely, by hacking the ruby source code some more.