C++ is *not* the only OO language (was: Re: PHP objects and public/private methods)

Giorgos Keramidas keramida at ceid.upatras.gr
Tue Sep 4 17:34:01 EEST 2007


On 2007-09-04 16:18, V13 <v13 at priest.com> wrote:
> On Tuesday 04 September 2007 13:37, Christos Ricudis wrote:
> > An xreiazesai na dhlwseis mia method san kati pou den einai oute
> > public oute protected, tote apla exeis kanei lan8asmeno OO design.
> > Rethink your objects.
>
> Oxi akribos:
>
> a) Paradeigma: Merikes fores o copy constructor kai o operator=()
> kanoyn paromoia doyleia, opote ftiaxneis mia boithitikh synartisi kai
> thn kaleis. Oi derived klaseis den exoyn kamia doyleia me ayth th
> synartisi:
>
> class A
> {
>   protected:
>     int n;
>
>   private:
>     void copy(const A &a)  { n=a.n; }
>
>   public:
>     A(const A &a) { copy(a); }
>     A operator=(const A &a) {copy(a); return(*this);}
> };
>
> b) Orismenes fores xreiazetai na xoriseis ta dedomena mias klashs se private
> kai protected (p.x. an tithetai thema memory allocation), oste na apofygeis
> melontika bugs. Se mikres klaseis den exei idiaiterh shmasia, alla se
> megalyteres exei.
>
>   Genika, klironomikotita mporeis na xrhsimopoihseis gia diaforoys logoys.
> Mporeis p.x. na 'metalakseis' thn arxiki klash, na thn 'employtiseis', na
> thn 'ylopoihseis' (an eixe pure virtuals) klp. Otan skopeveis sth 2h
> periptosi "xreiazetai" merikes fores na diloseis os private kapoies apo tis
> synartiseis h/kai ta dedomena.
>
> > Christos Ricudis
> <<V13>>
>
> p.s. <flame> Milame gia C++ panta, giati se otidipote allo to OOP
> einai apo pathetic eos apla yparkto </flame>
> p.s.2. <flame> Nai, ayto symperilambanei kai thn python kai th ruby
> kai thn java.</flame>
> p.s.3 Prosopikes apopseis...

Σεβαστές οι προσωπικές απόψεις, αλλά διαφωνώ...

<flame-bite-as-expected>

Σε παραπέμπω στο CLOS[1] της Common Lisp, για μια άλλη μορφή δυναμισμού
σε προγράμματα, βασισμένη σε "generic functions" αντί για την σχετικά
"κληρονομικότητα" που υποστηρίζει η C++.

[1] http://en.wikipedia.org/wiki/CLOS

Υπάρχει και object orientation χωρίς C++ και μάλιστα είναι αρκετά
ενδιαφέρον το CLOS, γιατί η κληρονομικότητα 'ανακαλύπτεται' δυναμικά από
το method signature που κάλεσες.

Για παράδειγμα, ένα κλασικό πρόγραμμα δοκιμής του inheritance είναι με
τα "σχήματα" και τα "φρούτα" που τόσο πολύ τα αγαπάνε τα C++ βιβλία.

1. Ορίζεις ένα class με όνομα 'shape':

   CL-USER> (defclass shape nil
                ((name :initform "Generic shape")))
   #<STANDARD-CLASS SHAPE>
   CL-USER>

2. Ορίζεις κάποια derivative classes:

   CL-USER> (defclass circle (shape)
                ((name :initform "Circular shape")))
   #<STANDARD-CLASS CIRCLE>
   CL-USER> (defclass rectangle (shape)
                ((name :initform "Rectangular shape")))
   #<STANDARD-CLASS RECTANGLE>
   CL-USER> (defclass square (rectangle)
                ((name :initform "Square shape")))
   #<STANDARD-CLASS SQUARE>
   CL-USER>

   Τώρα πλέον υπάρχει η ιεραρχία κλάσεων:

                         shape
                            |
             +--------------+---------------+
             |                              |
          circle                         rectangle
                                            |
                                          square

3. Ορίζεις μερικά αντικείμενα:

   CL-USER> (defparameter *v13* (make-instance 'circle))
   *V13*
   CL-USER> (defparameter *keramida* (make-instance 'square))
   *KERAMIDA*
   CL-USER>

Προσοχή... ακόμα δεν έχουν οριστεί οι *ΜΕΘΟΔΟΙ* των αντικειμένων αυτών.
Δεν πειράζει όμως.  Ας ορίσουμε μια generic function που τυπώνει το
όνομα ενός shape:

   CL-USER> (defgeneric shape-name (shape))
   #<STANDARD-GENERIC-FUNCTION SHAPE-NAME (0)>
   CL-USER>

Και τώρα μερικά 'specializations' αυτής της generic function:

   CL-USER> (defmethod shape-name ((s shape))
              (let ((name (slot-value s 'name)))
                (when name
                  (format t "~&~A" name))))
   #<STANDARD-METHOD SHAPE-NAME (SHAPE) {623A53E1}>
   CL-USER>

Μέχρι τώρα τυπώνει μόνο το 'name' attribute κάθε αντικειμένου:

   CL-USER> (mapcar (lambda (s)
                      (shape-name s))
              (list *v13* *keramida*))
   Circular shape
   Square shape
   (NIL NIL)
   CL-USER>

ok καλά ως εδώ.  Ας φτιάξουμε όμως μια `shape-name' generic function που
όταν το αντικείμενο είναι κύκλος, τυπώνει και τη λέξη " (circle)" μετά
το όνομά του.  Για να γίνει αυτό, αρκεί στο "defmethod" που ορίζει την
circle-specific function να προσθέσουμε το runtime qualifier :after έτσι
ώστε να τρέχει *ΜΕΤΑ* από οποιαδήποτε άλλη μέθοδο έχει κληρονομήσει το
circle object (π.χ. την generic (shape-name shape) function):

   CL-USER> (defmethod shape-name :after ((c circle))
              (format t " (circle)"))
   #<STANDARD-METHOD SHAPE-NAME :AFTER (CIRCLE) {61E27DE1}>
   CL-USER>

Αρκεί αυτό.  Πλέον, η συμπεριφορά των circle objects έχει αλλάξει σε
runtime:

   CL-USER> (mapcar (lambda (s)
                      (shape-name s))
                    (list *v13* *keramida*))
=> Circular shape (circle)
   Square shape
   (NIL NIL)
   CL-USER>

Πρόσεξε τη γραμμή με το "=>" marker!

Δεν είναι μόνο η C++ ενδιαφέρουσα "object oriented" γλώσσα, λοιπόν.

Υπάρχουν και πιο "δυναμικές" γλώσσες, με πιο ευέλικτες, επεκτάσιμες,
well-designed μορφές OO-programming.

</flame-bite-as-expected>




More information about the Linux-greek-users mailing list