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
class A1, A2, A3
def m1 ...
def m2 ...
end
class A2, A5, A7
def n1 ...
def n2 ...
end
class A1, A2, A3 = CL_123
def ...
end
class X
include CL_123
end
# approx. same as including X in the original CL_123 class list: A1, A2, A3, X
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.
class A, B common_body endcan 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 endtranslates into:
class C_AB ab_body end C_AB.freeze class A, B include C_AB endIncluding 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.
class A; def x; end; end class B; def x; end; endis just a lengthy way of writing
module M; def x; end; end class A; include M; end class B; include M; endwhich 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
endplus include Foo.
I believe your reasoning is flawed: you're comparing
class A, B, Cand module on different basis; you seem to consider
class A, B, Cwhen 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
endis very, very similar to
class Bar; include Foo end
module Foo; def foo; 1 end end class Bar; include Foo end
Please tell me if I missed the point completely.
-- Mauricio Fernández
class A; def x; end; end class B; def x; end; endis just a lengthy way of writing
module M; def x; end; end class A; include M; end class B; include M; endwhich 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
endplus include Foo.
I believe your reasoning is flawed: you're comparing
class A, B, Cand module on different basis; you seem to consider
class A, B, Cwhen 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
endis very, very similar to
class Bar; include Foo end
module Foo; def foo; 1 end end class Bar; include Foo end
Please tell me if I missed the point completely.
-- Mauricio Fernández
Back to RCRchive.
RCR Submission page and RCRchive powered by Ruby, Apache, RuWiki (modified), and RubLog