ruby picture

RCR 247: Multi-class definition

Submitted by itsme213 (Sat Apr 17 03:04:28 UTC 2004)

Abstract

Allow for the body of a class definition to apply to a set of classes, not just to a single class.

Problem

Say I have classes A1, A2,...An. Sometimes one subset of these classes has one set of shared behaviors: say A1, A2, A3 share m1(), m2().

Perhaps another subset share different behaviors: say A2, A5, A7 share n1(), n2().

Extracting this commonality using Ruby's single inheritance is difficult. Extracting it using a module can take quite a lot of refactoring work; this may be a worthwhile only if that module will be widely reused later.

The alternative is code duplication

Proposal

Ruby's incremental partial class definition offers a solution. If we call each partial class definition a "classlet":

Analysis

This borrows the approach used in CSS: no explicit class-like inheritance. You simply list all the selectors that you want to share a common set of stylings.

E1, E2, E3 {
  display: block;
}

This might also encourage more classes to be defined in this incremental style, which brings its own pros/cons.

Implementation

class A, B
  common_body
end
can translate roughly into:
class A
  common_body
end
class B
  common_body
end

... although I am not sure that side effects should occur twice.

The optional second and third parts of the proposal may be implementable by:

class A, B = C_AB
  ab_body
end

translates into:

class C_AB
  ab_body
end

C_AB.freeze
class A, B
  include C_AB
end

Including a class in another class behaves like textual insertion of the included class body. Again, I'm not sure if it might be better to carry the original context along e.g. closures.

ruby picture
Comments Current voting

You seem to be suggesting that:

class A; def x; end; end
class B; def x; end; end
is just a lengthy way of writing
module M; def x; end; end
class A; include M; end
class B; include M; end
which it isn't. In the first example you have two different methods (both called x). In the second example you have ONE method, present in the method search path of two classes.

It's not clear which case you're addressing, since you present them as interchangeable. Also, in your implementation, you're doing "include C" where C is a class. (That won't work.) In general this seems to be a kind of parallel-universe Ruby, where things don't work quite as they do in Ruby and therefore have to be fixed. I think you'll find that Class and Module objects do what you need quite elegantly.

-- David Black


You say "Extracting it using a module can take quite a lot of refactoring work; this may be a worthwhile only if that module will be widely reused later."

I don't see why

class A, B, C
  def foo; 1 end
end

is better than

module Foo
  def foo; 1 end
end
plus include Foo.

I believe your reasoning is flawed: you're comparing

class A, B, C
and module on different basis; you seem to consider
class A, B, C
when you know already some implementation will be shared amongst different classes, and module only when you realize this _afterwards_.

The similariry of your 'classlets' to regular modules is even more striking when one reads the 2nd and 3rd (optional) proposals.

class A, B, C = Foo
  def foo; 1 end
end
class Bar; include Foo end
is very, very similar to
module Foo; def foo; 1 end end
class Bar; include Foo end

Please tell me if I missed the point completely.

-- Mauricio Fernández


Strongly opposed 4
Opposed 0
Neutral 0
In favor 0
Strongly advocate 0
ruby picture
If you have registered at RCRchive, you may now sign in below. If you have not registered, you may sign up for a username and password. Registering enables you to submit new RCRs, and vote and leave comments on existing RCRs.
Your username:
Your password:

ruby picture

Powered by .