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