Inheritence as a tool vs. Inheritence as a design bug



I am starting a new thread and use a new subject.

The reason is that my original mail was a reply to a proposal, and I
(quite sharply) replied that this would be wrong.

I never argued for a non-oo interface to Glib or Gtk2 in general.

Personally, I am against needless use of oo-syntax for non-oo cases, as
it does complicates things for me, since I will always look for objects
or classes in these cases, but I might be the exception.

So could we leave the original thread to the filename functions and
their API.

In this thread, I'll represent some ideas for thought, but I do not
propose major changes, or any changes at all, it's just food for
thought.

On Thu, Jan 08, 2004 at 08:55:51AM -0500, Ross McFarland <rwmcfa1 neces com> wrote:
examples (of places where class static functions have to be accessable though
inheritance) do exist within gtk2-perl. a trivial example would be if i wanted
to create a new type of button that had an extra method or two:

[example that subclasses a class that has constructors, objects,
methods...]

(I assume that we all have a pretty similar idea of what subclassing,
inheritence etc. means and do not expect that our definitions of it differ
in any significant way).

there is a sligh difference in what is going on here, but we can't rule out
the possiblity that someone will want to make their own child of
Glib::Idle.

We can. First of all, Glib::Idle is a package (syntactically) and a class
(semantically, because of it's single function that expects a class
argument).

A package is a namespace in perl, and incidentally, it is also used for
classes. These are distinct things and represented differently in many
languages (e.g., C++), but in perl, the same syntax is used for them.

For namespaces no concept of inheritence exists. It doesn't apply, because
it is difficult to prescribe a useful semantic for it.

Now, if we want to subclass the example, Glib::Idle, then we have to
look at at least three cases:

1. single inheritance, class

   Glib::Idle, just as many other de-factor classes in Glib, only has a
   single method.

   By not using method syntax for this function, you do not lose
   anything, as

      *add = \&Glib::Idle::add;

   is not really more difficult than

      use base Glib::Idle::;

   it's more to type, but it's not particularly difficult to get the
   effect of subclassing.

   Using classes hints that there is indeed a common theme between all
   methods, often exemplified by objects (static classes are equivalent to
   singleton objects, so an object is always involved).

   For example:

      Gtk2->init;

   _does_ work on an object, if you insist, the gtk2-application/library,
   precisely named "Gtk2". However:

      Glib::Idle->add (...

   does _not_ work on the Glib::Idle object. It does not create a
   Glib::Idle object (at least in perl) and it does not apply to
   Glib::Idle objects, since there aren't. They do apply to the glib event
   system, and one could argue that there might be some equivalents to
   Glib::Idle somewhere, but it's not reflected in perl nor in the C API.

2. single inheritence, namespace

   Now, to packages. Glib, to me, is a purely a namespace.
   Glib::install_exception_handler and Glib::filename_to_unicode have no
   common theme, they don't work on objects either.

   Now, "subclassing" this namespace has no useful semantics, as Glib is
   not a class. In perl it can be used as a class, due to it's syntax,
   but that's something different.

   So what semantics would a Glib class have that can install exception
   handlers and convert filenames? Inheriting only makes sense when you
   create a subclass and inherit functionality of your super class.

   However, even if it is imaginable that someone might need both the
   install_exception_handler and filename functionality in it's
   subclass, it's not a sane object oriented design.

   Using inheritence in such a case would be bad design, the oo-equivalent
   of spaghetti code. Allowing that is one thing, explicitly supporitng
   and promoting bad style is another thing, and IMHO better left to other
   scripts/modules/languages.

3. multiple inheritence

   Multiple inheritence changes everything, of course, since you can
   mix-and-match your subclass.

   So let's fetch some add method because we are a Glib::Idle class:

      use base Glib::Idle::;


   Of course, we also want filename methods on our objects:

      use base Glib::;

   And we also get the exception handler management for free.

   Multiple inheritence, as used in this example, is not solving any
   problem, it's a pure hack to important unrelated methods as static
   methods into another namespace.

What I wanted to show is that no matter how much you use the -> syntax
over :: (or importing, which would help actual programmers most, since
they have least to type and abstract for this kind of functionality), it
does not help a bad design.

"->" does not magically help people subclass functionality from a
package. C does not have "->" but it's still possible to write gtk+ in
it. Thinking that syntax is a magic tool to enable good oo design is
wrong. Good design comes from well-though-out API's, and as we saw with
gtk+, it can take a few iterations until you come up with something
generic and reasonable.

I even argue that blindly using "->" is a bad thing, if the reasons behind
it are not understood, since it promotes subclassing, which often is
the wrong thing (one example is DynaLoader, which requires subclassing,
something that as-of-today is known as one of the worse decisions in perl
history. But back when it was created, subclassing was new and often was
used in cases where it made no sense, and today every module author has to
suffer(1)).

Lastly, and again, I am not proposing throwing the Gtk2 API overboard. I
used it extensively for some time, and don't remember having had much of
a problem with static methods, since in the majority of cases, it made
sense. "install_exception_handler" is not something that I would have made
a method (because of the cited reasons), but I did not use it myself so
far, so couldn't take offense :)

(1) Nowadays there is a "workaround" known as XSLoader which has a sane
non-oo interface, but it unfortunately can't be used with Gtk2 because
of it's unportable use of dl_load_flags.

Which gives yet another example. What semantics does Glib->dl_load_flags
have for users of Glib? It's a method, and required by DynaLoader, but it
does not make sense, and inheritence here is not a gift but a bug.

-- 
      -----==-                                             |
      ----==-- _                                           |
      ---==---(_)__  __ ____  __       Marc Lehmann      +--
      --==---/ / _ \/ // /\ \/ /       pcg goof com      |e|
      -=====/_/_//_/\_,_/ /_/\_\       XX11-RIPE         --+
    The choice of a GNU generation                       |
                                                         |



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]