OOP and inheritance

For the Compleat Fan
Locked
newBert
Posts: 156
Joined: Fri Oct 28, 2005 5:33 pm
Location: France

OOP and inheritance

Post by newBert »

In chapter 17 of the NewLISP Manual (Object-Oriented Programming in newLISP) polymorphism is described clearly and simply. That shows how NewLISP can adapt easily to apparently complex things...

I studied, with my poor knowledge and competence in computer science, the notion of inheritance and here is a little script which attempts to illustrate the question.

Please, would you critically examine it so as to let me know wether I've well understood the concept.

Code: Select all

#!/usr/bin/newlisp

(context 'rectangle)
; Class 'rectangle' with a constructor method
(define (rectangle:rectangle (width 30) (height 15))
	(set 'w width)
	(set 'h height)
	(set 'nam "rectangle"))
	
(define (perimeter)
	(string "(" w " + " h ") x 2 = " (mul (add w h) 2)))
	
(define (area)
	(string w " x " h " = " (mul w h)))
	
(define (measure)
	(println "A " nam " of " w " by " h)
	(println "has a surface area of " (area) ",")
	(println "and a perimeter of " (perimeter) ".\n"))
	
(context MAIN)

(context 'square)
; Class 'square' inherits from 'rectangle'
(new rectangle)
; Constructor of 'square'
(define (square:square (side 10))
	(set 'w side)
	(set 'h side)
	(set 'nam "square"))

(context MAIN)

; main program
(new rectangle 'fig1)
(fig1 27 12)
(fig1:measure)

(new square 'fig2)
(fig2 13)
(fig2:measure)
I think there is also a little polymorphism. I don't use the colon operator there... yet it would be better, sorry.
;)

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Very good - clear and direct!

I wondered whether the first (context MAIN) was needed. But in fact I think it demonstrates that (context 'square) isn't part of context rectangle although it inherits from it, neither is it a nested context (which don't exist...). So leaving it in is good!

newBert
Posts: 156
Joined: Fri Oct 28, 2005 5:33 pm
Location: France

Post by newBert »

cormullion wrote:Very good - clear and direct!

I wondered whether the first (context MAIN) was needed. But in fact I think it demonstrates that (context 'square) isn't part of context rectangle although it inherits from it, neither is it a nested context (which don't exist...). So leaving it in is good!
Yes, it was both intentional and conditioning by a distant practice of Basic or Basic-like language (with its 'block' ... 'end block', etc.).

I think it's just a little more readable. And I would like to modify those definitions in a very NewLISP way, using lists and colon operator as described in the User Manual (chapter 17)... to compare clearness and efficiency.
:)

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Post by m i c h a e l »

Hi newBert!

Inheritance can be used in a number of ways. The one most commonly discussed is the "is a" type of inheritance (the one used in your code), which models a classification relationship between objects. Mixins and implementation inheritance are two other types.

Your code uses the earlier context-based way of doing OOP, which was found to have weaknesses. The way I would do that now is:

Code: Select all

;; a rectangle constructor:
(define (rectangle:rectangle (width 30) (height 15)) (list rectangle width height))

;; a method defined using let to get the rectangle's width and height:
(define (rectangle:perimeter r) 
   (let  (w (r 1) h (r 2)) (string "(" w " + " h ") x 2 = " (mul (add w h) 2)))
)

;; a method defined using straight indexing:
(define (rectangle:area r) (string (r 1) " x " (r 2) " = " (mul (add (r 1) (r 2)))))

;; a method defined using rectangle's area and perimeter methods:
(define (rectangle:measure r) 
   (println "A " (r 0) " of " (r 1) " by " (r 2)) 
   (println "has a surface area of " (:area r) ", ") 
   (println "and a perimeter of " (:perimeter r) ".\n")
)

;; a square is a rectangle
(new rectangle 'square)

;; a square constructor
(define (square:square (side 10)) (list square side side))

;; main program
(set 'fig1 (rectangle 27 12))
(:measure fig1)

(set 'fig2 (square 13))
(:measure fig2)
Programming this way takes a little getting used to, but once you do, it starts to feel a lot more nimble than heavier OOP frameworks (I never did grok Ocaml's object system).

m i c h a e l

P.S. I think Lutz mentioned somewhere on the club that (context MAIN) should be used before beginning a new context. Sorry for not looking it up.

Fanda
Posts: 253
Joined: Tue Aug 02, 2005 6:40 am
Contact:

Post by Fanda »

I could never abandon my version of OOP, so I wrote a new version:
http://www.intricatevisions.com/source/newlisp/oop.lsp

And using it:

Code: Select all

(load "oop.lsp")

(set 'Rectangle
  (object ()
    width 30 height 15
    nam "rectangle"

    init (fn ((w 30) (h 15)) (set 'width w 'height h))
    perimeter (fn () (string "(" width " + " height ") x 2 = " (mul (add width height) 2)))
    area (fn () (string width " x " height " = " (mul width height)))
    measure (fn ()
     (println "A " nam " of " width " by " height)
     (println "has a surface area of " (area) ",")
     (println "and a perimeter of " (perimeter) ".\n"))
))

(set 'Square
  (object (Rectangle)
    nam "square"
    init (fn ((side 10)) (set 'width side 'height side))
))

;; main program
(set 'fig1 (obj-init Rectangle 27 12))
(obj-do 'fig1 (measure))

(set 'fig2 (obj-init Square 13))
(obj-do 'fig2 (measure))
I like it because it is compact and has a different feel to it.

Fanda

newBert
Posts: 156
Joined: Fri Oct 28, 2005 5:33 pm
Location: France

Post by newBert »

m i c h a e l wrote:Hi newBert!
Your code uses the earlier context-based way of doing OOP, which was found to have weaknesses.
I was aware of the weakness of my code. It was an adaptation of what I learnt about OOP through Python first. I like your version which is closer to the "newLISP spirit" than mine (which is perhaps just a little educational),
Fanda wrote:I could never abandon my version of OOP ( ... )
I like it because it is compact and has a different feel to it.
and I like Fanda's version too, which is closer to OOP standard (so to speak), maybe a little clearer (particularly for a beginner), as we can see in language like Python, Rebol and probably others that I don't know ...

I'm going to study both ways trying to avoid dissipating my efforts.

In any case, thank you for your very interesting replies.

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

Fanda's ways is better because its indeed for the beginner more readable..

perhpas the newlisp manual needs this extention ->

;; The object initiation
;; is done by pre-defining the object-class.

(define object-class:object-class)

;; Now the object initiation with an object-class
;; defined in a list because that is OOP.
;; object-class is a context symbol!

(set 'object '(object-class "attribute and methods go here"))

;; A class function

(define (object-class:pick x) (x 1))

;; A polymorphism

(:pick object)
-- (define? (Cornflakes))

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Post by m i c h a e l »

There's no doubt in my mind I would have preferred Fanda's way of doing OOP when I first came to newLISP. I've struggled with many different ways of doing objects in this language (maybe six so far), but this latest way feels the most native to newLISP. An important part of this is that the objects are used functionally (without mutable state). Without this, it's not FOOP.

We are free to use any frameworks we wish in newLISP, including Fanda's. The problem with frameworks is they must be included (and maintained). So far, I've managed to get by without a framework.

So use whatever makes you happy (that's why we code in newLISP, isn't it?). As for me, I'll keep exploring FOOP, wherever it may lead :-)

m i c h a e l

P.S. I'm still working on the FOOP introduction and hope to have it finished soon!

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

here: http://newlisp.org/index.cgi?page=newLISP-FOOP I have put together a page how FOOP came about and what makes it peculiar for newLISP.

Lutz

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

Lutz wrote:here: http://newlisp.org/index.cgi?page=newLISP-FOOP I have put together a page how FOOP came about and what makes it peculiar for newLISP.

Lutz
Very clear and good paper Lutz!
and a special thanks to Micheal for his work!
(Micheals examples are a real mind mixer sometimes ..this is a compliment!..;-)

FOOP it is ;-)
-- (define? (Cornflakes))

newBert
Posts: 156
Joined: Fri Oct 28, 2005 5:33 pm
Location: France

Post by newBert »

m i c h a e l wrote: We are free to use any frameworks we wish in newLISP, including Fanda's. The problem with frameworks is they must be included (and maintained). So far, I've managed to get by without a framework.
Yes I agree. This was a dilemna for me before...
Lutz wrote:here: http://newlisp.org/index.cgi?page=newLISP-FOOP I have put together a page how FOOP came about and what makes it peculiar for newLISP.
...but Lutz's paper finishes convincing me there is a real NewLISP way (and modern way) of doing OOP.

Nevertheless Fanda's work is an interesting and concrete demonstration of what NewLISP is able to do and as far as it can go ...

I'm only a humble and occasional NewLISP user. I'm admiring before all your work. I take a lot of things but I'm incapable of returning so much with my modest contribution.

Thanks

Locked