From: Paul Brannan Date: 2002-02-01T01:12:13+09:00 Subject: Re: Policy Classes - Challenge On Thu, Jan 31, 2002 at 11:38:41AM +0900, John Carter wrote: > Basically it is the idea that the client of a library should... > * Not be forced to inherit from library objects. This is already in Ruby: # foo requires x to have a method bar def foo(x) x.bar end # X has a method bar, but look ma, no inheritance! class X def bar; end end foo(X.new) > * Should be able to plug in any suitable class provided by the > client or the library as the base class of a library class. This, as you said, can be done with mixins and a class factory: # implementation of a Foo goes here module FooMixin def foo super() end end # A factory for creating Foo classes def Foo(t) c = Class.new c.class_eval do include(t) include(FooMixin) end end # The base class we want to use for Foo module Bar def foo puts "foo!" end end MyFooClass = Foo(Bar) foo = MyFooClass.new foo.foo #=> foo! > * Should be able to plug in several orthoganal policy classes as > multiply inherited base classes. Here's a similar factory that takes multiple arguments: def Foo(*t) c = Class.new c.class_eval do t.each do |type| include(type) end include(FooMixin) end end > I believe that Ruby mixins whould be able to be able to do all the above > in a far far cleaner manner. Indeed item one is the obvious thing about > mixins. Mixins aren't at all needed for item one; that's one of the neat things about Ruby. Mixins are helpful for the other two items, but keep in mind that Alexandrescu's policies are all generated at compile-time, while Ruby's mixins are handled at run-time. Just because one solution isn't as clean as another doesn't make it any less useful. > My only problem is to think of a small, neat and compelling demonstration > of these concepts. His examples (with exception of threading policy) all > relate to C++ arcana that simply are "not an issue" in Ruby. They are, however, such a big issue in C++ that to not mention them would be foolish. > Question. Can you think of a neat and compelling use for this concept, I'm > prepare to write the code as a proof of concept. How about a persistence mechanism for objects, with configurable options for how to store those objects (consider what type of database, what types of locking must be done on those objects, what kinds of reference counting must be done to ensure that the object doesn't go away before all clients are done with it and that the object does go away when all clients are done with it, etc.). Just a thought; I've never considered using policies in Ruby code before, so I'm not sure if this is at all compelling. Paul