Extracting a parent class

Sorry about the newbie question but…

class A
attr_accessor :a
end

class B < A
attr_accessor :b
end

b = B.new
b.a = "some data"
b.b = "some more data"
a = b.???

How do I set ‘a’ from ‘b’ so that a is of class A and not class B? I
don’t want the extra info, I want just the subset of members found in
the parent class. Is there a way to cast?

TIA
Michael Garriss

I don’t know of a simple, direct way to do this.

Offhand it’s possible that you’re thinking in a
C++ fashion and should simply do it another way.

You could add a class method for B that would
create an instance of A and return it…

class B
def B.to_A
x = A.new
x.a = self.a
x
end
end

That’s consistent with the ordinary principles of
an object knowing how to convert itself and a child
class having knowledge of a parent but not vice versa.

Hal

···

----- Original Message -----
From: “Michael Garriss” mgarriss@earthlink.net
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, July 31, 2003 4:53 PM
Subject: Extracting a parent class

Sorry about the newbie question but…

class A
attr_accessor :a
end

class B < A
attr_accessor :b
end

b = B.new
b.a = “some data”
b.b = “some more data”
a = b.???

How do I set ‘a’ from ‘b’ so that a is of class A and not class B? I
don’t want the extra info, I want just the subset of members found in
the parent class. Is there a way to cast?


Hal Fulton
hal9000@hypermetrics.com

Answer:
a = b.class.superclass.new

Why:
b.class == B
b.class.superclass == A
b.class.superclass.new == A.new

Cheers,
Daniel.

···

On Fri, Aug 01, 2003 at 06:53:01AM +0900, Michael Garriss wrote:

Sorry about the newbie question but…

class A
attr_accessor :a
end

class B < A
attr_accessor :b
end

b = B.new
b.a = “some data”
b.b = “some more data”
a = b.???

How do I set ‘a’ from ‘b’ so that a is of class A and not class B? I
don’t want the extra info, I want just the subset of members found in
the parent class. Is there a way to cast?

TIA
Michael Garriss


Daniel Carrera | PGP: 6643 8C8B 3522 66CB D16C D779 2FDD 7DAC 9AF7 7A88
Math PhD. UMD | http://www.math.umd.edu/~dcarrera/pgp.html

          • Weekly Smile * * * * * * * * * * * * * * * * * * * * * * * *
            Sign in a hotel in Athens:
            Visitors are expected to complain at the office between the hours
            of 9 and 11 A.M. daily.

Sorry…I should have been more clear. While this works it does not
mantain the state. I would like all the members of ‘b’ that are class
A members to be set in ‘a’.

Daniel Carrera wrote:

···

Answer:
a = b.class.superclass.new

Why:
b.class == B
b.class.superclass == A
b.class.superclass.new == A.new

Cheers,
Daniel.

On Fri, Aug 01, 2003 at 06:53:01AM +0900, Michael Garriss wrote:

Sorry about the newbie question but…

class A
attr_accessor :a
end

class B < A
attr_accessor :b
end

b = B.new
b.a = “some data”
b.b = “some more data”
a = b.???

How do I set ‘a’ from ‘b’ so that a is of class A and not class B? I
don’t want the extra info, I want just the subset of members found in
the parent class. Is there a way to cast?

TIA
Michael Garriss

It is VERY possible that I should be doing it in another way. My
motivation: I have a client/server arch. The server maintains objects
and a database. When the client needs something I do not want the
client to have full access to all the info found in those server side
objects. Some of it would be bad for the client to know. I have
classes the client side can use and I add the additional things the
server knows about the object by creating a subclass of the client class
and then just adding the one or two ‘secret’ members. Does this make sense?

Hal E. Fulton wrote:

···

----- Original Message -----
From: “Michael Garriss” mgarriss@earthlink.net
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, July 31, 2003 4:53 PM
Subject: Extracting a parent class

Sorry about the newbie question but…

class A
attr_accessor :a
end

class B < A
attr_accessor :b
end

b = B.new
b.a = “some data”
b.b = “some more data”
a = b.???

How do I set ‘a’ from ‘b’ so that a is of class A and not class B? I
don’t want the extra info, I want just the subset of members found in
the parent class. Is there a way to cast?

I don’t know of a simple, direct way to do this.

Offhand it’s possible that you’re thinking in a
C++ fashion and should simply do it another way.

You could add a class method for B that would
create an instance of A and return it…

class B
def B.to_A
x = A.new
x.a = self.a
x
end
end

That’s consistent with the ordinary principles of
an object knowing how to convert itself and a child
class having knowledge of a parent but not vice versa.

Hal


Hal Fulton
hal9000@hypermetrics.com

Oh, sorry.
In that case I don’t imagine it’s possible by default because in general
there might not be an “obvious” way to turn class B into class A.

You should make a B#to_A method.

Cheers,
Daniel.

···

On Fri, Aug 01, 2003 at 07:09:07AM +0900, Michael Garriss wrote:

Sorry…I should have been more clear. While this works it does not
mantain the state. I would like all the members of ‘b’ that are class
A members to be set in ‘a’.

Daniel Carrera wrote:

Answer:
a = b.class.superclass.new

Why:
b.class == B
b.class.superclass == A
b.class.superclass.new == A.new

Cheers,
Daniel.

On Fri, Aug 01, 2003 at 06:53:01AM +0900, Michael Garriss wrote:

Sorry about the newbie question but…

class A
attr_accessor :a
end

class B < A
attr_accessor :b
end

b = B.new
b.a = “some data”
b.b = “some more data”
a = b.???

How do I set ‘a’ from ‘b’ so that a is of class A and not class B? I
don’t want the extra info, I want just the subset of members found in
the parent class. Is there a way to cast?

TIA
Michael Garriss


Daniel Carrera | PGP: 6643 8C8B 3522 66CB D16C D779 2FDD 7DAC 9AF7 7A88
Math PhD. UMD | http://www.math.umd.edu/~dcarrera/pgp.html

          • Weekly Smile * * * * * * * * * * * * * * * * * * * * * * * *
            Sign in a hotel in Athens:
            Visitors are expected to complain at the office between the hours
            of 9 and 11 A.M. daily.

Perhaps containment would be a better solution than inheritance?

class ClientThingy
attr :foo, :bar, :baz
end

class ServerThingy
attr :client_thingy

def initialize
@client_thingy = ClientThingy.new
end
end

Also, have you looked at DRb? It will allow you to have a clean
division between server-side and client-side.

···

Michael Garriss (mgarriss@earthlink.net) wrote:

It is VERY possible that I should be doing it in another way. My
motivation: I have a client/server arch. The server maintains objects
and a database. When the client needs something I do not want the
client to have full access to all the info found in those server side
objects. Some of it would be bad for the client to know. I have
classes the client side can use and I add the additional things the
server knows about the object by creating a subclass of the client class
and then just adding the one or two ‘secret’ members. Does this make sense?


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

Well, not laugh., but I am using DRb. I’ve had a difficult time
figuring out it all, seems to be a lack or docs or I’m just bad at
finding them.

example of what I am doing:

class ServerObject < ClientObject
def to_client_side_version
# blah
end
end

class Server
def get_me_an_obj
@server_obj.to_client_side_version
end
end

class Client
def ask_for_obj
@server.get_me_an_obj
end
end

this is a 3rd file that I called shared that I put on both sides

I know there must be another way, plz help

class ClientObject
end

Eric Hodel wrote:

···

Michael Garriss (mgarriss@earthlink.net) wrote:

It is VERY possible that I should be doing it in another way. My
motivation: I have a client/server arch. The server maintains objects
and a database. When the client needs something I do not want the
client to have full access to all the info found in those server side
objects. Some of it would be bad for the client to know. I have
classes the client side can use and I add the additional things the
server knows about the object by creating a subclass of the client class
and then just adding the one or two ‘secret’ members. Does this make sense?

Perhaps containment would be a better solution than inheritance?

class ClientThingy
attr :foo, :bar, :baz
end

class ServerThingy
attr :client_thingy

def initialize
@client_thingy = ClientThingy.new
end
end

Also, have you looked at DRb? It will allow you to have a clean
division between server-side and client-side.

I suppose that containment is a good idea but I do have methods that
expect objs of the client side base class. I could rewrite them to add
the check the class of the incoming obj. I think that I will just
continue to use to_SomeClass type methods. It’s just a pain to have to
keep them upto date.

Eric Hodel wrote:

···

Michael Garriss (mgarriss@earthlink.net) wrote:

It is VERY possible that I should be doing it in another way. My
motivation: I have a client/server arch. The server maintains objects
and a database. When the client needs something I do not want the
client to have full access to all the info found in those server side
objects. Some of it would be bad for the client to know. I have
classes the client side can use and I add the additional things the
server knows about the object by creating a subclass of the client class
and then just adding the one or two ‘secret’ members. Does this make sense?

Perhaps containment would be a better solution than inheritance?

class ClientThingy
attr :foo, :bar, :baz
end

class ServerThingy
attr :client_thingy

def initialize
@client_thingy = ClientThingy.new
end
end

Also, have you looked at DRb? It will allow you to have a clean
division between server-side and client-side.

Just in case anyone is following this, I have a new solution to my
problem. It only works if each instance variable in the parent class is
accessable. Anyone who can solve this or has a hint…plz tell me!
Here’s the test code:

module SuperCastable
def to_super
super_obj = self.class.superclass.new
instance_variables.each { |var|
begin
eval “super_obj.#{var[1…-1]} = #{var}”
rescue NoMethodError
end
}
super_obj
end
end

class A
attr_accessor :a
end

class B < A
include SuperCastable
attr_accessor :b
end

b = B.new
b.a = “some data”
b.b = “some more data”
a = b.to_super

Daniel Carrera wrote:

···

Oh, sorry.
In that case I don’t imagine it’s possible by default because in general
there might not be an “obvious” way to turn class B into class A.

You should make a B#to_A method.

Cheers,
Daniel.

On Fri, Aug 01, 2003 at 07:09:07AM +0900, Michael Garriss wrote:

Sorry…I should have been more clear. While this works it does not
mantain the state. I would like all the members of ‘b’ that are class
A members to be set in ‘a’.

Daniel Carrera wrote:

Answer:
a = b.class.superclass.new

Why:
b.class == B
b.class.superclass == A
b.class.superclass.new == A.new

Cheers,
Daniel.

On Fri, Aug 01, 2003 at 06:53:01AM +0900, Michael Garriss wrote:

Sorry about the newbie question but…

class A
attr_accessor :a
end

class B < A
attr_accessor :b
end

b = B.new
b.a = “some data”
b.b = “some more data”
a = b.???

How do I set ‘a’ from ‘b’ so that a is of class A and not class B? I
don’t want the extra info, I want just the subset of members found in
the parent class. Is there a way to cast?

TIA
Michael Garriss

Unless you were to use the Struct class instead of a normal class, in
which case you can tell what should stay and what should go.

e.g.

class Struct
def cast_as(klass)
raise “Not a Class” unless klass.kind_of?(Class)
raise “Not a Struct” unless klass.ancestors.include?(Struct)
obj = klass.new()
members.each do |name|
obj[name] = self[name] if obj.members.include?(name)
end
obj
end
end

StructA = Struct.new(‘StructA’,:alpha, :beta)
StructB = Struct.new(‘StructB’,:alpha, :beta, :gamma)
foo = Struct::StructB.new(1,2,3)
bar = foo.cast_as(Struct::StructA)
p foo,bar

With a bit more effort you could try a reverse castable object - ie.
one which would preserve members unused by the target class and copy all
instance variables, but I don’t think that that is what is required
here.

HTH,

Geoff

···

On Fri, Aug 01, 2003 at 07:12:19AM +0900, Daniel Carrera wrote:

Oh, sorry. In that case I don’t imagine it’s possible by default
because in general there might not be an “obvious” way to turn class B
into class A.

You should make a B#to_A method.

Or query based on interface – ask if it has the methods you expect, not
the inheritance.

···

On Thu, 2003-07-31 at 16:53, Michael Garriss wrote:

I suppose that containment is a good idea but I do have methods that
expect objs of the client side base class. I could rewrite them to add
the check the class of the incoming obj. I think that I will just
continue to use to_SomeClass type methods. It’s just a pain to have to
keep them upto date.

You can get at anything you want using #instance_eval.

···

Michael Garriss (mgarriss@earthlink.net) wrote:

Just in case anyone is following this, I have a new solution to my
problem. It only works if each instance variable in the parent class is
accessable. Anyone who can solve this or has a hint…plz tell me!


Eric Hodel - drbrain@segment7.net - http://segment7.net
All messages signed with fingerprint:
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

Very cool, thank you.

Eric Hodel wrote:

···

Michael Garriss (mgarriss@earthlink.net) wrote:

Just in case anyone is following this, I have a new solution to my
problem. It only works if each instance variable in the parent class is
accessable. Anyone who can solve this or has a hint…plz tell me!

You can get at anything you want using #instance_eval.