Class C < B < A


#1

Hi, I have this case:

class A ; end
class B < A ; end
class C < B ; end

a = A.new
b = B.new
c = C.new

I look for a way (***) to get the following results:

a)
a *** A => true
a *** B => false
a *** C => false

b)
b *** A => false (*1)
b *** B => true
b *** C => false

c)
c *** A => false (*2)
c *** B => true
c *** C => true

Note that I could use ===, so:
A === a => true
A === b => false

but in cases *1 and *2 the result is not what I want:

A === b => true (I want false)
A === c => true (I want false)

I could play with a.class.ancestors, but isn’t another way?

Thanks a lot.


#2

Iñaki Baz C. wrote:

I look for a way (***) to get the following results:

#instance_of? works for all cases except:

c *** B => true

Are you sure you need this to be true?


#3

El Martes 07 Abril 2009, Joel VanderWerf escribió:

I look for a way (***) to get the following results:

#instance_of? works for all cases except:

c *** B => true

Are you sure you need this to be true?

Yes. Basically A is String and B is a child of String with various
methods,
and C is a more specific class.

But I didn’t realize of #instance_of?, I will try with it.

Thanks.


#4

Iñaki Baz C. wrote:

Hi, I have this case:

class A ; end
class B < A ; end
class C < B ; end

a = A.new
b = B.new
c = C.new

I look for a way (***) to get the following results:

a)
a *** A => true
a *** B => false
a *** C => false

b)
b *** A => false (*1)
b *** B => true
b *** C => false

c)
c *** A => false (*2)
c *** B => true
c *** C => true

(…)

Thanks a lot.

The method #kind_of? gives the results you want.

regards,

Siep


#5

El Martes 07 Abril 2009, Siep K. escribió:

Iñaki Baz C. wrote:

a)
a *** A => true
a *** B => false
a *** C => false

b)
b *** A => false (*1)

b.kind_of? A
=> true

b *** B => true
b *** C => false

c)
c *** A => false (*2)

c.kind_of? A
=> true

c *** B => true
c *** C => true

(…)

Thanks a lot.

The method #kind_of? gives the results you want.

Not in the above cases. It’s the same as using === :frowning:


#6

El Martes 07 Abril 2009, Tim P.
escribió:> c.like? B => true

c.like? C => true

Again, I’m not proud of this code – it works, though, without being
too tricky.

So freak! :slight_smile:

Thanks a lot.


#7

On Apr 6, 2009, at 4:12 PM, Iñaki Baz C. wrote:

b *** C => false

but in cases *1 and *2 the result is not what I want:

A === b => true (I want false)
A === c => true (I want false)

Well, it’s kinda hackish but it does give the correct output. Tailor
to suit your needs:

class A
alias :like? :instance_of?
end

class B < A; end

class C < B
def like?( clazz )
return true if clazz == B
super
end
end

a = A.new
b = B.new
c = C.new

[A, B, C].each do |clazz|
puts “a.like? #{clazz.name} => #{a.like? clazz}”
end
puts

[A, B, C].each do |clazz|
puts “b.like? #{clazz.name} => #{b.like? clazz}”
end
puts

[A, B, C].each do |clazz|
puts “c.like? #{clazz.name} => #{c.like? clazz}”
end

==== OUTPUT ====
a.like? A => true
a.like? B => false
a.like? C => false

b.like? A => false
b.like? B => true
b.like? C => false

c.like? A => false
c.like? B => true
c.like? C => true

Again, I’m not proud of this code – it works, though, without being
too tricky.

Blessings,
TwP


#8

On 07.04.2009 00:41, Iñaki Baz C. wrote:

I look for a way (***) to get the following results:

#instance_of? works for all cases except:

c *** B => true
Are you sure you need this to be true?

Yes. Basically A is String and B is a child of String with various methods,
and C is a more specific class.

Frankly, I find this a bit spooky for several reasons: first, you
inherit String which IMHO is almost always a bad idea™. You should
consider using delegation, so you have

class B
attr_reader :str
end

class C < B; end

Then, you introduce inconsistencies in inheritance checking. That might
yield all sorts of surprises.

If you want to do it nevertheless, I’d probably go for a special method
which you override appropriately:

class Module
def class_of?(obj)
if self == String
self == obj.class
else
self === obj
end
end
end

class B < String
end

class C < B
end

classes = [String,B,C]
classes.each do |cl|
puts cl
o = cl.new

classes.each do |cl2|
print cl2, " ", cl2.class_of?(o), “\n”
end

puts “–”
end

Something along these lines.

Kind regards

robert


#9

On Mon, Apr 6, 2009 at 11:12 PM, Iñaki Baz C. removed_email_address@domain.invalid wrote:

b *** C => false

but in cases *1 and *2 the result is not what I want:

A === b => true (I want false)
A === c => true (I want false)

I could play with a.class.ancestors, but isn’t another way?

Thanks a lot.

You need to specify somewhere the root of the inheritance hierarchy
you’re interested in. Something like this:

class A
def like?(klass)
if klass == A
self.class == A
else
self.class <= klass
end
end
end

More generally, this will do what you want (at least, what I think you
want :wink:

module RootedClassComparison
def self.included(other)
module_eval {
define_method :like? do |klass|
if klass == other
self.class == other
else
self.class <= klass
end
end
}
end
end

class A
include RootedClassComparison
end
class B < A
end
class C < B
end
class D < C
end

a = A.new
b = B.new
c = C.new
d = D.new

klasses = [A, B, C, D]

test pinched from Tim’s example :slight_smile:

klasses.each do |clazz|
puts “a.like? #{clazz.name} => #{a.like? clazz}”
end
puts

klasses.each do |clazz|
puts “b.like? #{clazz.name} => #{b.like? clazz}”
end
puts

klasses.each do |clazz|
puts “c.like? #{clazz.name} => #{c.like? clazz}”
end
puts

klasses.each do |clazz|
puts “d.like? #{clazz.name} => #{d.like? clazz}”
end

Output:

a.like? A => true
a.like? B => false
a.like? C => false
a.like? D => false

b.like? A => false
b.like? B => true
b.like? C => false
b.like? D => false

c.like? A => false
c.like? B => true
c.like? C => true
c.like? D => false

d.like? A => false
d.like? B => true
d.like? C => true
d.like? D => true

Regards,
Sean


#10

El Martes 07 Abril 2009, Robert K.
escribió:> Frankly, I find this a bit spooky for several reasons: first, you

inherit String which IMHO is almost always a bad idea™. You should
consider using delegation, so you have

Thanks a lot. However I’ve already solved it by changing my classes
definitions so I don’t have that painful requeriment anymore :slight_smile: