Problem extending (adding methods) to class

I am trying to extend a class developed by someone else (its from the
ncurses-ruby lib). I need to add some fields and methods to it.

  1. I tried directly extending it the usual way.
    class MyForm < FORM

However, all attempts to access my methods would give a NoMethodError
on the base class Ncurses::FORM.

  1. I then looked up the source and copied the following on top of my
    class MyForm.

module Form
class FORM
attr_reader :user_object

  def user_object=(obj)
    @user_object = obj
  end
end

end

I changed user_object to “my_fields”. This approach works, but means i
cannot actually extend the class. I need a heirarchy below this each
adding its methods and data.

Now I am wondering whether my approach is wrong. Is the class
locked/final in some way?

I am aware of an alternative appoach: create an instance of FORM in a
class (no more inheritance). Use method_missing to call methods of
original class. However, before i make changes, would like to understand
if I am doing something wrong here.

Thanks.

Nit K. wrote:

I am trying to extend a class developed by someone else (its from the
ncurses-ruby lib). I need to add some fields and methods to it.

On further thought I am wondering if being inside a module makes that
class different. Like some sort of static or factory class. Nothing
coming up on google on “module classes” or classes within modules.

Could someone explain this or point me to a link. I read that modules
cannot be instantiated or subclasses - fine. What of classes declared in
them ?

Nit K. wrote:

Nit K. wrote:

I am trying to extend a class developed by someone else (its from the
ncurses-ruby lib). I need to add some fields and methods to it.

On further thought I am wondering if being inside a module makes that
class different. Like some sort of static or factory class. Nothing
coming up on google on “module classes” or classes within modules.

Could someone explain this or point me to a link. I read that modules
cannot be instantiated or subclasses - fine. What of classes declared in
them ?

why don’t you take advantage of open classes ?

you can write this :

class MyClass
attr_accessor :myfield
end

and then you can access myfield using any instance of that class . The
same goes with methods .

If you write :

class MyClass
def my_new_method
#some logic here
end
end

then , all your objects will have that method .

Class defined inside a module behaves exactly the same as if she was
defined
‘outside’ - it isn’t ‘static’ in any way.

(Following notes may either help you or not - I haven’t understood
totally where exactly your problem is.)

If you want to extend class ClassC defined inside module ModuleM , you
can
either write

module ModuleM
class ClassC
# add new methods here
end
end

or

class ModuleM::ClassC

add new methods here

end

Similarly if you want to subclass ClassC, you can do it inside ModuleM

module ModuleM
class ClassD < ClassC
# blah blah
end
end

or outside:

class ClassD < ModuleM::ClassC

blah blah

end

Sorry if I didn’t understand you at all…

Hi –

On Fri, 3 Oct 2008, Nit K. wrote:

I am trying to extend a class developed by someone else (its from the
ncurses-ruby lib). I need to add some fields and methods to it.

  1. I tried directly extending it the usual way.
    class MyForm < FORM

However, all attempts to access my methods would give a NoMethodError
on the base class Ncurses::FORM.

Methods you add to a subclass are not visible to instances of the
original class.

end
end

I changed user_object to “my_fields”. This approach works, but means i
cannot actually extend the class. I need a heirarchy below this each
adding its methods and data.

Now I am wondering whether my approach is wrong. Is the class
locked/final in some way?

No. If you want to add methods to it, you can just open it up and add
them:

require ‘rubygems’
require ‘ncurses’

class Ncurses::Form::FORM
def my_method
puts “Hello”
end
end

n = Ncurses::Form::FORM.new
n.my_method # Hello

David

No. If you want to add methods to it, you can just open it up and add
them:

require ‘rubygems’
require ‘ncurses’

class Ncurses::Form::FORM
def my_method
puts “Hello”
end
end

n = Ncurses::Form::FORM.new
n.my_method # Hello

David

That is precisely what i did. It worked. But I am unable to further
subclass it. Methods I am adding to the subclass are giving
NoMethodErrors.

Lex W. wrote:

Nit K. wrote:

Nit K. wrote:

I am trying to extend a class developed by someone else (its from the
ncurses-ruby lib). I need to add some fields and methods to it.

On further thought I am wondering if being inside a module makes that
class different. Like some sort of static or factory class. Nothing
coming up on google on “module classes” or classes within modules.

Could someone explain this or point me to a link. I read that modules
cannot be instantiated or subclasses - fine. What of classes declared in
them ?

why don’t you take advantage of open classes ?

you can write this :

class MyClass
attr_accessor :myfield
end

and then you can access myfield using any instance of that class . The
same goes with methods .

If you write :

class MyClass
def my_new_method
#some logic here
end
end

then , all your objects will have that method .

Are you by any chance saying the same thing i have done above, when i
copied the Module Class thing from the original source and added my
method and data to it ?

However, this much is working, but i need a heirarchy. I am unable to
extend this and add methods to it.

If the original class was declared as:

Module MyClass
class MYCLASS
attr_accessor :myfield
end
end

I can copy this, and add:
attr_accessor :newfield
This is okay.

But when i do:

class AnotherClass < MYCLASS
attr_accessor :anotherfield
end

then i get a NoMethodError pointing to MyClass::MYCLASS. I get no error
when instantiating AnotherClass, only when i access the method added.

I need a heirarchy of classes under Ncurses::FORM.

Hi –

On Fri, 3 Oct 2008, Nit K. wrote:

end

n = Ncurses::Form::FORM.new
n.my_method # Hello

David

That is precisely what i did. It worked. But I am unable to further
subclass it. Methods I am adding to the subclass are giving
NoMethodErrors.

Can you try this and tell me what you get?

class MyForm < Ncurses::Form::FORM
def a_new_method
puts “Hi”
end
end

MyForm.new.a_new_method

David

Hi –

On Fri, 3 Oct 2008, Nit K. wrote:

Similarly if you want to subclass ClassC, you can do it inside ModuleM
or outside:
class AForm < Ncurses::FORM
I don’t think it was exactly this, because there is no Ncurses::FORM.
Try the code in my previous post and see if it works for you. If not,
please post some actual code that triggers the error you’re talking
about. I can’t duplicate it.

David

Jakub Pavlík jn. wrote:

module ModuleM
class ClassC
# add new methods here
end
end

Thanks, this worked fine.

Similarly if you want to subclass ClassC, you can do it inside ModuleM

module ModuleM
class ClassD < ClassC
# blah blah
end
end

Not tried this.

or outside:

class ClassD < ModuleM::ClassC

blah blah

end

THIS did not work. I got NoMethodErrors trying this out. I spent many
hours checking and trying to see if some other error was happening.

I needed:
class AForm < Ncurses::FORM

class BForm < AForm
and so on.

So finally, i removed the < clause abd created an instance in the
initializer. And used “method_missing” to call methods of that instance.
This is working perfectly, i can keep subclassing … However, i still
want to understand what i did wrong. or what i am not understanding
about classes within modules.

Why create classes within modules ? Is it only a namespace issue - to
avoid clashes with other classes. Is it like java’s package?

Should we always create modules and packages inside them in a project
with many classes ? Currently I have only one module with common stuff
and a heriarchy of classes under no module.

David A. Black wrote:

Hi –

On Fri, 3 Oct 2008, Nit K. wrote:

Similarly if you want to subclass ClassC, you can do it inside ModuleM
or outside:
class AForm < Ncurses::FORM
I don’t think it was exactly this, because there is no Ncurses::FORM.
Try the code in my previous post and see if it works for you. If not,
please post some actual code that triggers the error you’re talking
about. I can’t duplicate it.

David

Maybe we are onto something. Your code works fine. But doesn’t FORM.new
require a fields object ? I tried many variations so i cant remember
what it was but here is the last one I have before i rewrote.

include Ncurses
include Ncurses::Form

class RBForm < FORM
attr_accessor :ffields
def initialize(fields)
super(fields)
@ffields = fields
end
def set_ffields(fields)
@ffields = fields
end
def get_ffields
@ffields
end
end

get_ffields throws a NoMethodError.
If i access ffields, that too gives an error.

It is instantiated thus:
f=RBQueryForm.new(fields);

RBQueryForm is subclassed from RBForm.

See if you can spot the error here itself. Otherwise I will try to cut
and make a tiny version that you can run and see.

Hi –

On Fri, 3 Oct 2008, Nit K. wrote:

please post some actual code that triggers the error you’re talking
include Ncurses
end
f=RBQueryForm.new(fields);

RBQueryForm is subclassed from RBForm.

See if you can spot the error here itself. Otherwise I will try to cut
and make a tiny version that you can run and see.

Please post some real code that contains the error. Otherwise it
just goes back and forth.

This code runs. I’ve changed super(fields) to super() because with an
argument I got an error (it expected zero arguments). I don’t know
exactly what the fields are supposed to consist of so I’ve used a
placeholder (“abc”).

require ‘rubygems’
require ‘ncurses’
include Ncurses
include Ncurses::Form

class RBForm < FORM
attr_accessor :ffields
def initialize(fields)
super()
@ffields = fields
end
def set_ffields(fields)
@ffields = fields
end
def get_ffields
@ffields
end
end

RBForm.new(“abc”).set_ffields(“abc”)

David

Nit K. wrote:

David A. Black wrote:

Hi –

On Fri, 3 Oct 2008, Nit K. wrote:

please post some actual code that triggers the error you’re talking

OK David, I will attach a file that comes with ncurses-ruby.
I have subclassed FORM with MyForm and tried to call a method.

(Once it works You can exit using C-c or alt-c.)

Strangely in the samples we made, FORM and FIELD take no params. This is
outside of the ncurses environment. In the sample i sent you earlier, i
tried to create a FIELD object, but it would take no params !!!
So i had no option but to take an independent fully working sample and
add a few lines.

Hi –

On Fri, 3 Oct 2008, Nit K. wrote:

(Once it works You can exit using C-c or alt-c.)

Strangely in the samples we made, FORM and FIELD take no params. This is
outside of the ncurses environment. In the sample i sent you earlier, i
tried to create a FIELD object, but it would take no params !!!
So i had no option but to take an independent fully working sample and
add a few lines.

OK, I think what’s happening here is that the FORM class is overriding
new, in such a way that it does not call initialize. So overriding
initialize doesn’t do anything.

I don’t have a solution worked out but I believe that’s the issue.

David

David A. Black wrote:

Hi –

On Fri, 3 Oct 2008, Nit K. wrote:

please post some actual code that triggers the error you’re talking
include Ncurses
end
f=RBQueryForm.new(fields);

RBQueryForm is subclassed from RBForm.

See if you can spot the error here itself. Otherwise I will try to cut
and make a tiny version that you can run and see.

Please post some real code that contains the error. Otherwise it
just goes back and forth.

This code runs. I’ve changed super(fields) to super() because with an
argument I got an error (it expected zero arguments). I don’t know
exactly what the fields are supposed to consist of so I’ve used a
placeholder (“abc”).

RBForm.new(“abc”).set_ffields(“abc”)

David
Sorry about not posting reeal code. I tried the same thing – to bring
it down to one file, but it won’t let me pass a parameter. When i say
only super() the sample is working. The original program goes ahead with
the field array - no error at that point. There are too many modules and
classes involved for me to put it all here. Still trying to post some
real code.

I thought you may straight away spot the error considering that I am
passing a param, and you are not. wait …

David A. Black wrote:

OK, I think what’s happening here is that the FORM class is overriding
new, in such a way that it does not call initialize. So overriding
initialize doesn’t do anything.

I don’t have a solution worked out but I believe that’s the issue.

Sorry if this sounds silly, i forgot to mention that i had attached
the source in my prev mail (f3.rb). Did you run it?

Thanks a lot for your time and thoughts.

ragav wrote:

You’ll see that FORM class has a singleton “new” method which always
returns a FORM object. Class#new is shadowed so you’ll never get a
descendant object

raise MyForm.new.class.inspect #=> Ncurses::Form::FORM

DelegateClass is a possible solution unless you want to muck with the
C sources.

–Cheers
–Ragav
Ah, i get it. Thanks for the link to DelegateClass - just had a look at
it.

For the moment, (as mentioned earlier), i created an instance of FORM,
and used method_missing to “delegate” calls to it after checking
respond_to?, now i can subclass that class as required.

Changing the C source will mean others will not be able to use, unless
they move to my modified source - don’t want that. Thanks for the info.

So my question again is: are classes declared within a module
typically/always factory classes like this – i mean with singleton new
methods?

Perhaps I should look thru the source code of Facets or some other
project to jump-start my ruby. Any suggestions?

On Oct 2, 7:54 pm, Nit K. [email protected] wrote:

Thanks a lot for your time and thoughts.

Posted viahttp://www.ruby-forum.com/.

David is right.

Before the line
raise “NULL” if my_form.get_fields().nil?

insert
raise Ncurses::Form::FORM.singleton_methods(false).join(" ") #=> new

You’ll see that FORM class has a singleton “new” method which always
returns a FORM object. Class#new is shadowed so you’ll never get a
descendant object

raise MyForm.new.class.inspect #=> Ncurses::Form::FORM

DelegateClass is a possible solution unless you want to muck with the
C sources.

–Cheers
–Ragav

Hi –

On Fri, 3 Oct 2008, Nit K. wrote:

David A. Black wrote:

OK, I think what’s happening here is that the FORM class is overriding
new, in such a way that it does not call initialize. So overriding
initialize doesn’t do anything.

I don’t have a solution worked out but I believe that’s the issue.

Sorry if this sounds silly, i forgot to mention that i had attached
the source in my prev mail (f3.rb). Did you run it?

Yes; that’s how I figured out that initialize wasn’t being called.

David

Hi –

On Fri, 3 Oct 2008, Nit K. wrote:

–Cheers
–Ragav
Ah, i get it. Thanks for the link to DelegateClass - just had a look at
it.

For the moment, (as mentioned earlier), i created an instance of FORM,
and used method_missing to “delegate” calls to it after checking
respond_to?, now i can subclass that class as required.

Why not use a module?

module MyForm
attr_accessor :myfields
def get_fields
@myfields
end
end

class Ncurses::Form::FORM
include MyForm
end

Changing the C source will mean others will not be able to use, unless
they move to my modified source - don’t want that. Thanks for the info.

So my question again is: are classes declared within a module
typically/always factory classes like this – i mean with singleton new
methods?

No; it’s relatively unusual (though not unheard of) to override new.

David