caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Re: [Caml-list] Restricting Method Overriding/Redefinition in Subclass
@ 2004-08-16  4:58 Jeff Schultz
  0 siblings, 0 replies; 6+ messages in thread
From: Jeff Schultz @ 2004-08-16  4:58 UTC (permalink / raw)
  To: Caml Mailing List; +Cc: John Prevost

> 1) Implementing multiple interfaces.
> 
> In Java, things sometimes get awkward if you want to work with values
> that implement multiple interfaces at once:
> 
> class MyThingy implements Colored, HasPoint {
>     ...
> }
> 
> Okay, so the difficulty in this set of classes and interfaces (which
> *has* actually bitten me in the wild fairly frequently) is that there
> is no way to declare a variable as "any object that is of both type
> Colored and type HasPoint."  If we do this:
> 
> interface ColoredHasPoint extends Colored, HasPoint { ... }
> 
> then MyThingy is not an instance of ColoredHasPoint.  It has all of
> the appropriate methods, but it was not *declared* to have this type. 
> Therefore, it does not have the correct type.  So you end up having to
> write:
> 
>     void useColoredHasPoint(Object o) {
>         Colored c = (Colored) o;
>         HasPoint h = (HasPoint) o;
>         ... = c.getColor();
>         ... = h.getPoint();
>     }
> 
> and obviously the system has now broken down.  AS long as you work
> with only one interface at a time, you're in fine shape.  As soon as
> you need more than one and have no other requirements, you're in
> trouble.  In O'Caml, of course, the above is trivial:
> 
>     let use_colored_has_point o =
>        let color = o#get_color () in
>        let point = o#get_point () in
>        ...

True enough, but I think of this as more to do with the convenience
provided by type inference's creation of names for types the
programmer didn't write.  So the type of use_colored_has_point is
something like

    < get_color : unit -> 'a; get_point : unit -> 'b; .. > -> ...

where type inference has come up with a new type that the programmer
could have written, but didn't have to.

One can get the same effect with Java 1.5's poor man's generics by
writing

    <T extends Colored & HasPoint> void useColoredHasPoint2(T o) {
        Color color = o.getColor();
	Point point = o.getPoint();
    }

so even though it's verbose, it's certainly possible.  (If it also had
typedef, it might not be all that bad.)

Of course, just because an object has both get_color and get_point, or
implements both Colored and HasPoint interfaces, doesn't mean that the
colour and point returned have any specific relationship to each
other, so it's not a given that mixing them on any arbitrary object
makes sense.  To be safe, one needs some way to check that they do go
together, perhaps a ColoredPoint interface or the discipline of saying
that this getPoint method is here because this object implements
HasPoint, and obeys HasPoint's contract with the programmer, whatever
that is, isn't always such a bad thing :-)


    Jeff Schultz

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] Restricting Method Overriding/Redefinition in Subclass
  2004-08-18 12:04     ` chris.danx
  2004-08-18 19:47       ` John Prevost
@ 2004-08-18 22:21       ` skaller
  1 sibling, 0 replies; 6+ messages in thread
From: skaller @ 2004-08-18 22:21 UTC (permalink / raw)
  To: chris.danx; +Cc: John Prevost, Caml Mailing List

On Wed, 2004-08-18 at 22:04, chris.danx wrote:

>  Separating subtyping from subclassing is 
> something I'd read about (in the context of polymorphism and 
> subclassing) and thought was very useful. 

You aren't going far enough. Subtyping is a *semantic* notion.
Whether a class satisfies the 'is a' relation or not is the issue.

In Ocaml, if a class has a type which is not an *Ocaml* 
subtype of another it probably isn't a subtype semantically ***

The converse is not true. Just because Ocaml thinks your
class has a subtype of another classes type does NOT
mean it actually is a subtype -- you still need to check
the methods to make sure the 'is a' property holds. 
If you override some method and give it an incompatible
behaviour you don't have a subtype (you'll just get weird
bugs!)

*** It is possible to have a class which acts semantically
'as' another but is not ruled by Ocaml as a subtype.
A trivial example of this is when you have two methods
called 'size' in one class and 'length' in another
that do the same job -- but happen to be encoded with
distinct names. You'll have to use a wrapper to fix this
without invading one of the classes (and then probably
breaking something else).

-- 
John Skaller, mailto:skaller@users.sf.net
voice: 061-2-9660-0850, 
snail: PO BOX 401 Glebe NSW 2037 Australia
Checkout the Felix programming language http://felix.sf.net



-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] Restricting Method Overriding/Redefinition in Subclass
  2004-08-18 12:04     ` chris.danx
@ 2004-08-18 19:47       ` John Prevost
  2004-08-18 22:21       ` skaller
  1 sibling, 0 replies; 6+ messages in thread
From: John Prevost @ 2004-08-18 19:47 UTC (permalink / raw)
  To: chris.danx; +Cc: Caml Mailing List

On Wed, 18 Aug 2004 13:04:44 +0100, chris.danx <chris.danx@ntlworld.com> wrote:
> > 2) Subclasses that are not subtypes
> 
> The first one is easy to understand, but the second example took a while
> to get my head around.  I think I understand the implications of it now,
> although it is still a bit unclear to me how the reuse works in this
> example.  I sort of understand it, but bits of it are unclear.  Need to
> think about it for a while.

Well, to be honest, the example is not a very good example.  With the
linked lists and doubly linked lists, the amount of code that is
re-used is pretty small compared to the amount of work that needs to
be done to re-use it.  Try looking at the section on binary methods in
the OCaml manual (Section 3.16) for a much much simpler example of a
subclass that is not a subtype.

Both section 3 and section 5 of the manual are very very good things
to read to get a handle on this object system.

John.

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] Restricting Method Overriding/Redefinition in Subclass
  2004-08-14 16:28   ` John Prevost
@ 2004-08-18 12:04     ` chris.danx
  2004-08-18 19:47       ` John Prevost
  2004-08-18 22:21       ` skaller
  0 siblings, 2 replies; 6+ messages in thread
From: chris.danx @ 2004-08-18 12:04 UTC (permalink / raw)
  To: John Prevost; +Cc: Caml Mailing List

John Prevost wrote:

[snip]

> let use_get_x o = o#get_x
> 
> Here, the function "use_get_x" can be used on instances of any class
> that contains a method get_x : unit -> int.  This is called
> "structural subtyping".  The subtype relationship is based purely on
> what methods exist, not on what classes have been declared to be
> subclasses of others.

I didn't realise OCaml supported this.  I wanted to write code like that 
but didn't realise it was possible in OCaml.  This opens the door to a 
new way of writing programs.  Thanks!

> At this point, you may be wondering "Why is O'Caml like this?  Is it a
> good thing to separate subtyping and subclassing this way?"  So I'll
> give a couple of examples of how this type discipline is less of a
> pain than the one used by Java.

It's not so strange to me.  Separating subtyping from subclassing is 
something I'd read about (in the context of polymorphism and 
subclassing) and thought was very useful.  It gives you the ability to 
write code that works over different classes of object, without 
specifying the precise type of the object (it's type is implied by the 
methods it has).  This is why I didn't realise OCaml provides the 
ability to do this.  I'd assumed that the typing rules of OCaml enforced 
the fact that the methods and classes had to exist before the inference 
of the type was done and that it'd be one of those classes.  Thinking 
about it that doesn't make much sense.

Now it's clear how the new immediate objects work.  It was a bit 
puzzling before, as there seemed no way to use them.  Immediate objects 
seem to make it trivial to write something like a proxy providing you 
know the methods before hand.  A more interesting case would be if you 
didn't know the methods before hand but you could access them in someway 
and build objects at runtime and you could somehow guarantee the result 
was compatible.  Not sure how that'd fit with OCamls typing scheme, but 
it's interesting to think about.

> 1) Implementing multiple interfaces.

...

> 2) Subclasses that are not subtypes

...

The first one is easy to understand, but the second example took a while 
to get my head around.  I think I understand the implications of it now, 
although it is still a bit unclear to me how the reuse works in this 
example.  I sort of understand it, but bits of it are unclear.  Need to 
think about it for a while.

> I hope my long-winded explanation was useful.

Very!  OCaml is a big language - in the sense there's a lot of power 
there - and some of it is still hidden to me so I appreciated your 
explanation.


Thanks,
Chris

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] Restricting Method Overriding/Redefinition in Subclass
  2004-08-14  0:03 chris.danx
@ 2004-08-14  7:38 ` skaller
  2004-08-14 16:28   ` John Prevost
  0 siblings, 1 reply; 6+ messages in thread
From: skaller @ 2004-08-14  7:38 UTC (permalink / raw)
  To: chris.danx; +Cc: Caml Mailing List

On Sat, 2004-08-14 at 10:03, chris.danx wrote:

> Perhaps a radically different solution is best?  I chose an OO solution 
> so that new classes could be trivially added to the system.

There is another kind of solution you might investigate.

Instead of trying to unify all your data types using 
abstraction -- classes provide abstraction --
use summation instead.

A summation solution looks like:

type obj = [
  | `A of a 
  | `B of b * obj 
  | `C of c * obj * obj
]

using polymorphic variants. In order to 
'do something' with each object, including
children, you write a 'visitor' style function:

let rec iter x = match x with
  | `A  a -> do_a a
  | `B (b ,kid) -> do_b b; iter kid
  | `C (c, k1, k2) -> iter k1; do_c c; iter k2


When you need to add a new object type to this
system you have to add the method for handling
it, just as in the OO solution.

The difference is that the method doesn't go
in with the data lexically, but separately
in the visitor function. Ocaml will make sure
you don't forget.

This kind of solution is more flexible than the OO
style solution, since you can write many different
kinds of 'visitor' style functions without invading
your data descriptions. The downside is that the
code for each kind is scattered through the program,
whereas with classes its localised lexically.

Which solution is best depends on how homogenous
your object kinds are. If they're all instances
of a single abstraction -- use classes.

If they're heterogenous objects -- use summation.

You can of course mix both solutions together -- abstract
what really is abstract, and unify what is not 
using variants.

-- 
John Skaller, mailto:skaller@users.sf.net
voice: 061-2-9660-0850, 
snail: PO BOX 401 Glebe NSW 2037 Australia
Checkout the Felix programming language http://felix.sf.net



-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Caml-list] Restricting Method Overriding/Redefinition in Subclass
@ 2004-08-14  0:03 chris.danx
  2004-08-14  7:38 ` skaller
  0 siblings, 1 reply; 6+ messages in thread
From: chris.danx @ 2004-08-14  0:03 UTC (permalink / raw)
  To: Caml Mailing List

Hi,

Methods provide access control in the form of private or public methods, 
but I am in a position where I would like the client to extend some 
methods but not others, and would like some advice if possible.

class type virtual base_class =
    object (self)

    method add_child    (c : base_class) -> unit
    method remove_child (c : base_class) -> unit
    method remove_all_child (c : base_class) -> unit

    method private children : unit -> base_class iterator


    method virtual perform_action unit -> unit
end;;

perform_action is supposed to do something with the rendering state and 
call each of it's childrens perform_action methods in turn (unless it's 
a leaf).  base_class is the base class for all objects in a scene graph.

I have narrowed the behaviour of perform_action down to three 
possibilities.  Either it does something before calling it's children, 
it does something after calling it's children or it does something 
before and after calling it's children.  This leads either to one class 
with additional two methods (recode base_class to include pre and post 
ops) or three classes with either a pre or post call or both.  To ensure 
objects don't do extra work I was considering the three class solution 
or a set of classes paramterised by closures which resolve to 
essentially the same thing. e.g.

class type prechild_class =
    object(self)
       inherit base_class

    method virtual pre_op unit -> unit
    method perform_action unit -> unit
end;;

or

(* pre_op_func is a typically a closure and essentially behaves
    like a hook.
  *)
class type prechild_class (pre_op_func : unit -> unit) =
    object(self)
       inherit base_class

    ...

    method perform_action unit -> unit
end;;

Basically pre_op can be overridden to perform the desired function, with 
perform_action calling it before iterating over the children or a 
closure can be provided and called by perform_action.  Is it possible to 
prevent the redefinition of perform_action by a subclass?  If not I can 
live with it, but if there is a way it would serve to enforce the 
intended behaviour of the class.  Namely that it should do what it needs 
to do and call it's children somewhere in perform_action.  One could 
rely on the subclass to encode this behaviour, but it would be very easy 
for programmers to forget this which leads to a violation of what could 
be regarded as a class invariant.

Perhaps a radically different solution is best?  I chose an OO solution 
so that new classes could be trivially added to the system.  It just 
occured to me that the same functionality can be provided with records 
where all the operations are closures.  Pass in the relevant functions 
to a function and get a closure with all the operations of the original 
class.  It's entirely possible I'm over analysing the problem and should 
use something simpler as I've done that before on more than one occassion.

Any advice is welcome.


Cheers,
Chris

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2004-08-18 22:21 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-08-16  4:58 [Caml-list] Restricting Method Overriding/Redefinition in Subclass Jeff Schultz
  -- strict thread matches above, loose matches on Subject: below --
2004-08-14  0:03 chris.danx
2004-08-14  7:38 ` skaller
2004-08-14 16:28   ` John Prevost
2004-08-18 12:04     ` chris.danx
2004-08-18 19:47       ` John Prevost
2004-08-18 22:21       ` skaller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).