Eigenclass not extensible?

... in the particular case where the method already exists.

== Example

class Cls; end
class Cls2; end

def Cls.somemethod
  "defined in Cls"
end

Cls.somemethod #=> "defined in Cls"

module Mod
  def somemethod
    "defined in Mod"
  end
end

Cls.extend Mod
Cls2.extend Mod

Cls.somemethod #=> "defined in Cls"
Cls2.somemethod #=> "defined in Mod"

Why doesn't Cls.somemethod gets overrided ?

···

--
Cheers,
  zimbatm

http://zimbatm.oree.ch

IMO because Cls is already having its particular singleton class (when
you defined the somemethod). (but I may be completely wrong).

./alex

···

--
.w( the_mindstorm )p.
---
(http://themindstorms.blogspot.com)

On 6/28/06, Jonas Pfenniger <zimba.tm@gmail.com> wrote:

... in the particular case where the method already exists.

== Example

class Cls; end
class Cls2; end

def Cls.somemethod
  "defined in Cls"
end

Cls.somemethod #=> "defined in Cls"

module Mod
  def somemethod
    "defined in Mod"
  end
end

Cls.extend Mod
Cls2.extend Mod

Cls.somemethod #=> "defined in Cls"
Cls2.somemethod #=> "defined in Mod"

Why doesn't Cls.somemethod gets overrided ?

--
Cheers,
  zimbatm

http://zimbatm.oree.ch

Jonas Pfenniger wrote:

... in the particular case where the method already exists.

== Example

class Cls; end
class Cls2; end

def Cls.somemethod
  "defined in Cls"
end

Cls.somemethod #=> "defined in Cls"

module Mod
  def somemethod
    "defined in Mod"
  end
end

Cls.extend Mod
Cls2.extend Mod

Cls.somemethod #=> "defined in Cls"
Cls2.somemethod #=> "defined in Mod"

Why doesn't Cls.somemethod gets overrided ?

B/c of what #extend actually does. It is the same as:

  class << Cls
    include Mod
  end

Try this:

  def Cls.somemethod
    super + "defined in Cls"
  end

T.

Modules are inserted into the inheritance chain. So if you do something like:

class A
   def x
     "x"
   end
end

module X
   def x
     "y"
   end
end

class A
   include X
end

a = A.new

a.x (Look for #x in my singleton class, can't find it? Ok, look for it in A, aha! found it! return "x")

class B
   include X
end

b = B.new
b.x (Look for #x in my singleton class, can't find it? Ok, look for it in B, can't find it? Ok, look for it in X, aha! found it return "y")

As you can see, it doesn't really have anything to do with the fact that it's a singleton class, it's just how modules work.

The reason why using #extend can override something declared in an objects class is because the singleton class is earlier in the inheritance chain than the actual class of the object. extend includes the module into the singleton class which puts it earlier than the object's real class.

···

On Jun 28, 2006, at 1:13 PM, Jonas Pfenniger wrote:

... in the particular case where the method already exists.

== Example

class Cls; end
class Cls2; end

def Cls.somemethod
"defined in Cls"
end

Cls.somemethod #=> "defined in Cls"

module Mod
def somemethod
   "defined in Mod"
end
end

Cls.extend Mod
Cls2.extend Mod

Cls.somemethod #=> "defined in Cls"
Cls2.somemethod #=> "defined in Mod"

Why doesn't Cls.somemethod gets overrided ?

-- Cheers,
zimbatm

http://zimbatm.oree.ch

Not sure if I read it correctly but in both cases the singleton method
is the first looked for, than the class and than any included modules,
so considering the chain of inheritance I would say that the singleton
is the leaf.

./alex

···

--
.w( the_mindstorm )p.
---
(http://themindstorms.blogspot.com)

On 6/28/06, Logan Capaldo <logancapaldo@gmail.com> wrote:

On Jun 28, 2006, at 1:13 PM, Jonas Pfenniger wrote:

> ... in the particular case where the method already exists.
>
> == Example
>
> class Cls; end
> class Cls2; end
>
> def Cls.somemethod
> "defined in Cls"
> end
>
> Cls.somemethod #=> "defined in Cls"
>
> module Mod
> def somemethod
> "defined in Mod"
> end
> end
>
> Cls.extend Mod
> Cls2.extend Mod
>
> Cls.somemethod #=> "defined in Cls"
> Cls2.somemethod #=> "defined in Mod"
>
> Why doesn't Cls.somemethod gets overrided ?
>
> --
> Cheers,
> zimbatm
>
> http://zimbatm.oree.ch
>

Modules are inserted into the inheritance chain. So if you do
something like:

class A
   def x
     "x"
   end
end

module X
   def x
     "y"
   end
end

class A
   include X
end

a = A.new

a.x (Look for #x in my singleton class, can't find it? Ok, look for
it in A, aha! found it! return "x")

class B
   include X
end

b = B.new
b.x (Look for #x in my singleton class, can't find it? Ok, look for
it in B, can't find it? Ok, look for it in X, aha! found it return "y")

As you can see, it doesn't really have anything to do with the fact
that it's a singleton class, it's just how modules work.

The reason why using #extend can override something declared in an
objects class is because the singleton class is earlier in the
inheritance chain than the actual class of the object. extend
includes the module into the singleton class which puts it earlier
than the object's real class.

Effectively :

module Mod
def somemethod
   "defined in Mod"
end
end

class Cls3
  def self.somemethod
    super + " and in Cls3"
  end
end

Cls3.somemethod #=> NoMethodError: super: no superclass method `somemethod'

Cls3.extend Mod

Cls3.somemethod #=> "defined in Mod and in Cls3"

# But...

Cls3.ancestors #=> [Cls3, Object, Kernel]
class << Cls3
  ancestors
end #=> [Mod, Class, Module, Object, Kernel]

So in theory, the eigenclass is effectively BEFORE anything else but
in doesn't show up in the ancestors.

Last question : do you know if there is a workaround to make class
extension work like class inclusion ? Where the module is BEFORE the
eigenclass ?

···

--
Cheers,
  zimbatm

http://zimbatm.oree.ch

Jonas Pfenniger wrote:

Last question : do you know if there is a workaround to make class
extension work like class inclusion ? Where the module is BEFORE the
eigenclass ?

Not possible. And I'm not sure why you want to do that? You can get a
module in BEFORE it class by including it into the object's singleton.

T.

Well I have some legacy class methods that I want to extend. Therefor,
I'd like to use `super` in my extension module and not vice-versa.

···

On 29/06/06, transfire@gmail.com <transfire@gmail.com> wrote:

Jonas Pfenniger wrote:
> Last question : do you know if there is a workaround to make class
> extension work like class inclusion ? Where the module is BEFORE the
> eigenclass ?

Not possible. And I'm not sure why you want to do that? You can get a
module in BEFORE it class by including it into the object's singleton.

--
Cheers,
  zimbatm

http://zimbatm.oree.ch

Jonas Pfenniger wrote:

···

On 29/06/06, transfire@gmail.com <transfire@gmail.com> wrote:
> Jonas Pfenniger wrote:
> > Last question : do you know if there is a workaround to make class
> > extension work like class inclusion ? Where the module is BEFORE the
> > eigenclass ?
>
> Not possible. And I'm not sure why you want to do that? You can get a
> module in BEFORE it class by including it into the object's singleton.

Well I have some legacy class methods that I want to extend. Therefor,
I'd like to use `super` in my extension module and not vice-versa.

subclass the legacy classes (?)

T.

No, change the classes themselves trough module inclusion.

···

On 29/06/06, transfire@gmail.com <transfire@gmail.com> wrote:

subclass the legacy classes (?)

--
Cheers,
  zimbatm

http://zimbatm.oree.ch

trans was asking, if you wanted to use "super" why not just subclass them? Really, sometimes inheritance really is the solution.

That said, the usual way to wrap a method like that is:

class LegacyClass
   alias original_version_of_some_method some_method
   def some_method
     ...
     original_version_of_some_method(...) # effectively 'super'
   end
end

···

On Jun 29, 2006, at 12:13 PM, Jonas Pfenniger wrote:

On 29/06/06, transfire@gmail.com <transfire@gmail.com> wrote:

subclass the legacy classes (?)

No, change the classes themselves trough module inclusion.

-- Cheers,
zimbatm

http://zimbatm.oree.ch

trans was asking, if you wanted to use "super" why not just subclass
them? Really, sometimes inheritance really is the solution.

Ah sorry I didn't understood it that way. This is not possible in my
situation. I'm using Camping. And Camping does funky stuff. It defines
a bunch of modules with class methods, etc.. trough evaling it's own
code. If you want to run a Camping app, you have to use the evaled
code.

That said, the usual way to wrap a method like that is:

class LegacyClass
   alias original_version_of_some_method some_method
   def some_method
     ...
     original_version_of_some_method(...) # effectively 'super'
   end
end

Hmm that seems to be feasible.

I've just had a devil idea :smiley:

class Cls4; end
class << Cls4
  def somemethod; "legacy"
end

mod = Module.new
mod.module_eval do
  define_method :somemethod, &Cls4.method(:somemethod).to_proc
end

Cls4.extend mod
class << Cls4
  def somemethod; super + " redefined !"; end
end

Cls4.somemethod #=> "legacy redefined !"

Thanks everybody :slight_smile:

···

On 29/06/06, Logan Capaldo <logancapaldo@gmail.com> wrote:

--
Cheers,
  zimbatm

http://zimbatm.oree.ch