Γλώσσες Προγραμματισμού Εφαρμογών - ΜΕΠΒ20 Διάλεξη 8 Τάξεις και Αντικείμενα Παπαϊωάννου Αθανάσιος Π.Μ.Σ. «Εφαρμοσμένη Πληροφορική» Χειμερινό Εξάμηνο 20 16-20 17
Στην Python όλα είναι αντικείμενα... Όλα στην Python είναι αντικείμενα Ήδη έχουμε δεί κάποια σχετικά δείγματα: hello.upper() list3.append( a ) dict2.keys() Αυτά μοιάζουν με κλήση μεθόδων Java ή C++ Νέες τάξεις αντικειμένων μπορούν να οριστούν πολύ εύκολα να οριστούν επιπρόσθετα στους ενσωμετωμένους τύπους της Pyhon Στην πραγματικότητα, ο προγραμματισμός στη Python γίνεται κυρίως με έναν οντοκεντρικό τρόπο
Οντοκεντρισμός Στον οντοκεντρισμό προγραμματισμό ένα πρόγραμμα φτιάχνεται από πολλά συνεργαζόμενα αντικείμενα Αντί να είναι το «συνολικό πρόγραμμα», ένα αντικείμενο είναι ένα μικρό κομμάτι του προγράμματος το οποίο συνεργάζεται με άλλα αντικείμενα Τα αντικειμένα συνεργάζονται με άλλα αντικείμενα ανταλλάσσοντας μηνύματα με αυτά και χρησιμοποιώντας το ένα τις ικανότητες του άλλου
Αντικείμενο Ένα αντικείμενο είναι ένα αυτόνομο κομμάτι του προγράμματος με κώδικα και δεδομένα Ένα κύριο χαρακτηριστικό της προσέγισης αντικειμένων είναι να σπάμε το πρόβλημα σε μικρότερα κατανοητά μέρη (διαίρει και βασίλευε) Τα αντικείμενα έχουν σύνορα που μας επιτρέπουν να αγνούμε αχρείαστες λεπτομέρειες Χρησιμοποιούσαμε αντικείμενα έως τώρα: αντικείμενα συμβολοσειρών, ακεραίων, λιστών, ευρετηρίων..
movies = list() movie1 = dict() movie1['director'] = 'James Cameron' movie1['title'] = 'Avatar' movie1['release Date'] = '18 December 2009' movie1['running Time'] = '162 minutes' movie1['rating'] = 'PG-13' movies.append(movie1) movie2 = dict() movie2['director'] = 'David Fincher' movie2['title'] = 'The Social Network' movie2['release Date'] = '01 October 2010' movie2['running Time'] = '120 min' movie2['rating'] = 'PG-13' movies.append(movie2)
Ορισμοί Τάξη ένα πρότυπο, π.χ. Dog Μέθοδος ή Μήνυμα Μια ορισμένη ικανότητα της τάξης, π.χ. bark() Πεδίο ή χαρακτηριστικό Ένα στοιχείο δεδομένων στην τάξη, π.χ. Length Αντικείμενο ή Στιγμιότυπο Ένα συγκεκριμένο στιγμιότυπο μιας τάξης, π.χ. Lassie
Ορολογία: Τάξη Ορίζει τα αόριστα χαρακτηριστικά μιας κατηγορίας πραγμάτων (αντικειμένων) συμπεριλαμβανομένων των γνωρισμάτων τους (πεδία ή ιδιότητες) και των συμπεριφορών τους (αυτά που μπορούν να κάνουν ή να τους κάνεις, ή τις μεθόδους τους και τις ικανότητές τους) Είναι σαν ένα εργοστάσιο που προδιαγράφει τη φύση κάποιων κατασκευών ή πραγμάτων Για παράδειγμα, η τάξη Dog θα αποτελείτο από χαρακτηριστικά που μοιράζονται όλα τα σκυλιά, όπως είναι η καταγωγή και το χρώμα του τριχώματος, και από συμπεριφορές, όπως είναι οι ικανότητες να γαβγίζουν και να κάθονται
Ορολογία: Στιγμιότυπο Μπορούμε να έχουμε στιγμιότυπα μιας τάξης ή ένα συγκεκριμένο αντικείμενο Αυτό το στιγμιότυπο είναι μια ενσάρκωση ενός πραγματικού αντικειμένου της τάξης που δημιουργείται κατά την εκτέλεση του προγράμματος Για παράδειγμα, το αντικείμενο Lassie είναι ένα στιγμιότυπο της τάξης Dog Το σύνολο των τιμών των γνωρισμάτων ενός συγκεκριμένου αντικειμένου αποτελούν την κατάστασή του Ένα αντικείμενο αποτελείται από τη κατάστασή του και τη συμπεριφορά του. Η τελευταία ορίζεται στην τάξη του αντικειμένου
Ορολογία: Μέθοδος Οι μέθοδοι μιας τάξης ορίζουν τις ικανότητες όλων των αντικειμένων της Οι μέθοδοι μεταβάλλουν την κατάσταση ενός αντικειμένου κάνοντας κάποια επεξεργασία στα δεδομένα του επιτρέπουν να επικοινωνήσουμε με ένα αντικείμενο και να του στείλουμε μήνυμα Οι μέθοδοι περιγράφονται συνήθως από ρήματα Για παράδειγμα, η Lassie, ως σκύλος, έχει την ικανότητα να γαβγίζει. Επομένως, bark() είναι μία από τις μεθόδους της τάξης Dog στην οποία ανήκει η Lassie. Άλλες μέθοδοι που μπορεί να έχει είναι οι sit(), eat() και walk() Καλώντας μία μέθοδο σε ένα συγκεκριμένο αντικείμενο, η συμπεριφορά θα αφορά το συγκεκριμένο αντικείμενο
Παράδειγμα Τάξης Το class είναι δεσμευμένη λέξη class PartyAnimal: x = 0 Κάθε αντικείμενο PartyAnimal ενθηλακώνει κάποιο κομμάτι κώδικα και κάποια δεδομένα (που ορίζεται από την τάξη του) Λέμε στο αντικείμενο να εκτελέσει τον κώδικα της μεθόδου party() def party(self) : self.x = self.x + 1 print("so far",self.x) an = PartyAnimal() an.party() an.party() an.party() Δημιουργία αντικειμένου
Ορίζοντας μια Τάξη class name: statements
Πεδία name = value Παράδειγμα: class Point: x = 0 y = 0 # main p1 = Point() p1.x = 2 p1.y = -5 point.py 1 2 3 class Point: x = 0 y = 0 Μπορούν να οριστούν μέσα στην τάξη (όπως φαίνεται εδώ) ή μέσα στους κατασκευαστές (συνηθέστερα) Η Python δεν υποστηρίζει πραγματική ενθηλάκωση ή πεδία private Βασίζεται στον καλούντα να «είναι καλός» και να μην πειράξει τα πεδία του αντικειμένου Από την άποψη του οντοκεντρικού προγραμματισμού, η Java είναι πιο ολοκληρωμένη γλώσσα (!)
Χρήση Τάξης import class client programs must import the classes they use point_main.py 1 2 3 4 5 6 7 8 9 10 from Point import * # main p1 = Point() p1.x = 7 p1.y = -3... # Python objects are dynamic (can add fields any time!) p1.name = "Tyler Durden"
Μέθοδοι Αντικείμένων def name(self, parameter,..., parameter): statements Το self πρέπει να είναι η πρώτη παράμετρος για κάθε μέθοδο αντικειμένου Αναπαριστά αναφορά στο ίδιο το αντικείμενο (ισοδύναμο με το this στη Java) Πρέπει να προσπελάσει τα πεδία του αντικειμένου μέσω της αναφοράς στο ίδιο το αντικείμενο self class Point: def translate(self, dx, dy): self.x += dx self.y += dy...
«Υπονοούμενη» Παράμετρος (self) Java: this, υπονοούμενη public void translate(int dx, int dy) { x += dx; // this.x += dx; y += dy; // this.y += dy; } Python: self, εννοούμενη def translate(self, dx, dy): self.x += dx self.y += dy Άσκηση: Γράψτε τις μεθόδους distance, set_location και distance_from_origin
Ανακαλύπτοντας Ικανότητες Η εντολή dir() παραθέτει τις ικανότητες μιας τάξης Αγνοήστε αυτές με τις κάτω παύλες αυτές χρησιμοποιούνται από την ίδια τη Python Οι υπόλοιπες είναι πραγματικές μέθοδοι που μπορούν να κληθούν στα αντικείμενα της τάξης Αυτό είναι αντίστοιχο με την εντολή type(), η οποία μας λέει κάτι για μια μεταβλητή >>> x = list() >>> type(x) <type 'list'> >>> dir(x) [' add ', ' class ', ' contains ', ' delattr ', ' delitem ', ' delslice ', ' doc ', ' eq ', ' setitem ', ' setslice ', ' str ', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] >>>
Διάρκεια Ζωής Αντικειμένου Τα αντικείμενα δημιουργούνται, χρησιμοποιούνται και καταστρέφονται Αυτά γίνονται με ειδικά μπλοκ εντολών (μεθόδους) που καλούνται Τη στιγμή της δημιουργίας του νέου αντικειμένου (κατασκευαστής) Τη στιγμή της καταστροφής του αντοκειμένου (καταστροφέας) Οι κατασκευαστές χρησιμοποιούνται πολύ Οι καταστροφείς χρησιμοποιούνται σπάνια
Παράδειγμα point.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from math import * class Point: x = 0 y = 0 def set_location(self, x, y): self.x = x self.y = y def distance_from_origin(self): return sqrt(self.x * self.x + self.y * self.y) def distance(self, other): dx = self.x - other.x dy = self.y - other.y return sqrt(dx * dx + dy * dy)
Κλήση Μεθόδων Οι μέθοδοι αντικειμένων μπορούν να κληθούν με 2 τρόπους: (η τιμή του self μπορεί να είναι εννοούμενη ή να δοθεί ως όρισμα 1) object.method(parameters) ή 2) Class.method(object, parameters) Παράδειγμα: p = Point(3, -4) p.translate(1, 5) Point.translate(p, 1, 5)
Ειδικές Μέθοδοι init del len iter contains getitem
Κατασκευαστές def init (self, parameter,..., parameter): statements Ο κατασκευαστής είναι μια ειδική μέθοδος με το όνομα init Παράδειγμα: class Point: def init (self, x, y): self.x = x self.y = y... Πώς θα ήταν δυνατό να κατασκευάσουμε ένα αντικείμενο Point() χωρίς παραμέτρους και να πάρουμε το (0, 0);
Παράδειγμα Κατασκευής Αντικειμένου class PartyAnimal: x = 0 name = "" def init (self, nam): self.name = nam print(self.name,"constructed") def party(self) : self.x = self.x + 1 print(self.name,"party count",self.x) s = PartyAnimal("Sally") s.party() Οι κατασκευαστές μπορούν να έχουν περισσότερες παραμέτρους. Αυτές μπορούν να χρησιμοποιηθούν για να θέσουν τιμές στα γνωρίσματα του συγκεκριμένου στιγμιοτύπου της τάξης (δηλ. για το συγκεκριμένο αντικείμενο). j = PartyAnimal("Jim") j.party() s.party()
Πολλαπλά Στιγμιότυπα Μπορούμε να δημιουργήσουμε πολλά αντικείμενα η τάξη είναι το πρότυπο για τα αντικείμενα Μπορούμε να αποθηκεύσουμε κάθε ξεχωριστό αντικείμενο σε δική του ξεχωριστή μεταβλητή Αυτό αποκαλείται «πολλαπλά στιγμιότυπα» της ίδιας τάξης Κάθε στιγμιότυπο έχει το δικό του αντίγραφο των μεταβλητών στιγμιοτύπου
tostring και str def str (self): return string Ισοδύναμη με τη μέθοδο tostring της Java (η οποία μετατρέπει ένα αντικείμενο σε συμβολοσειρά) Καλείται αυτόματα όταν καλούνται η str ή η print Άσκηση: Γράψτε μια μέθοδο str για τα αντικείμενα Point που επιστρέφει συμβολοσειρές της μορφής "(3, -14)" def str (self): return "(" + str(self.x) + ", " + str(self.y) + ")"
Συνολική Τάξη Point point.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from math import * class Point: def init (self, x, y): self.x = x self.y = y def distance_from_origin(self): return sqrt(self.x * self.x + self.y * self.y) def distance(self, other): dx = self.x - other.x dy = self.y - other.y return sqrt(dx * dx + dy * dy) def translate(self, dx, dy): self.x += dx self.y += dy def str (self): return "(" + str(self.x) + ", " + str(self.y) + ")"
Υπερφόρτωση Τελεστών Μπορεί κανείς να ορίσει συναρτήσεις ώστε οι ενσωματωμένοι τελεστές της Python να μπορούν να χρησιμοποιηθούν με ειδικό τρόπο σε μια τάξη Operator Class Method - neg (self, other) + pos (self, other) * mul (self, other) / truediv (self, other) Unary Operators - neg (self) + pos (self) Operator Class Method == eq (self, other)!= ne (self, other) < lt (self, other) > gt (self, other) <= le (self, other) >= ge (self, other)
Άσκηση Exercise: Write a Fraction class to represent rational numbers like 1/2 and -3/8. Fractions should always be stored in reduced form; for example, store 4/12 as 1/3 and 6/-9 as -2/3. Hint: A GCD (greatest common divisor) function may help. Define add and multiply methods that accept another Fraction as a parameter and modify the existing Fraction by adding/multiplying it by that parameter. Define +, *, ==, and < operators.
Δημιουργώντας Εξαιρέσεις raise ExceptionType("μήνυμα") χρήσιμες όταν κάποιος χρησιμοποιεί το αντικείμενό σας αντικανονικά τύποι: ArithmeticError, AssertionError, IndexError, NameError, SyntaxError, TypeError, ValueError Παράδειγμα: class BankAccount:... def deposit(self, amount): if amount < 0: raise ValueError("negative amount")...
Κληρονομικότητα Τάξεων Όταν δημιουργούμε μια νέα τάξη μπορούμε να επαναχρησιμοποιήσουμε μια υπάρχουσα τάξη και να υιοθετήσουμε όλες τις ικανότητες της υπάρχουσας τάξης και έπειτα να προσθέσουμε κάτι ώστε να έχουμε τη νέα μας τάξη Άλλη μια μορφή αποθήκευσης και επαναχρησιμοποίησης Γράφεται μια φορά, χρησιμοποιείται πολλές φορές Η θυγατρική κλάση είναι μια εξειδικευμένη έκδοση της πατρικής τάξης έχει τις μεθόδους και τις μεταβλητές της πατρικής και ακόμη περισσότερα
Παράδειγμα Κληρονομικότητας Λέμε ότι οι θυγατρικές τάξεις επεκτείνουν ή εξειδικεύουν τις πιο γενικές πατρικές τάξεις
Σύνταξη Κληρονομικότητας class name(superclass): statements Παράδειγμα: class Point3D(Point): z = 0... # Point3D extends Point Η Python επίσης υποστηρίζει πολλαπλή κληρονομικότητα class name(superclass,..., superclass): statements (if > 1 superclass has the same field/method, conflicts are resolved in left-to-right order)
Παράδειγμα Κληρονομικότητας class PartyAnimal: x = 0 name = "" def init (self, nam): self.name = nam print(self.name,"constructed") def party(self) : self.x = self.x + 1 print(self.name,"party count",self.x) s = PartyAnimal("Sally") s.party() j = FootballFan("Jim") j.party() j.touchdown() class FootballFan(PartyAnimal): points = 0 def touchdown(self): self.points = self.points + 7 self.party() print(self.name,"points",self.points) Η FootballFan είναι μια τάξη που επεκτείνει την PartyAnimal. Επομένως, έχει τις ικάνότητες της PartyAnimal και περισσότερες.
Παράδειγμα Πολλαπλής Κληρονομικότητας >>> class B(object):... def init (self):... self.value = 'b'... >>> class C(A, B): pass... >>> C().value 'a' >>> class C(B, A): pass... >>> C().value 'b'
Κλήση Μεθόδων Υπερτάξης μέθοδοι: class.method(object, parameters) κατασκευαστές: class. init (parameters) class Point3D(Point): z = 0 def init (self, x, y, z): Point. init (self, x, y) self.z = z def translate(self, dx, dy, dz): Point.translate(self, dx, dy) self.z += dz
Υπερφόρτωση Συναρτήσεων στην Python Υπερφόρτωση είναι η χρήση διαφορετικών τύπων παραμέτρων με το ίδιο όνομα συνάρτησης Η επιλογή της συγκεγκριμένης συνάρτησης που χρησιμοποιείται γίνεται στη μετάφραση του προγράμματος C++, Java, etc. Επομένως, στην Python (που είναι δυναμική γλώσσα) το σκεπτικό της υπερφόρτωσης δεν εφαρμόζεται με αυτήν την έννοια. Όμως, η υπερφόρτωση συναρτήσεων μπορεί να πραγματοποιηθεί και να δημιουργήσουμε εναλλακτικές συναρτήσεις κατά την εκτέλεση: Οι συναρτήσεις που οι εναλλακτικές τους υλοποιήσεις αποφασίζονται κατά την εκτέλεση ανάλογα με τον τύπο των παραμέτρων τους αναφέρονται γενικά ως πολυμέθοδοι (multimethods) class PartyAnimal: def init (self, x=0, nam=""): self.name = nam self.x = x print(self.name,"constructed") def party(self) : self.x = self.x + 1 print(self.name,"party count",self.x) Ισοδύναμο, με το να έχω 3 κατασκευαστές: Έναν χωρίς παραμέτρους, έναν με μία παράμετρο και έναν με δύο παραμέτρους
Σύνοψη Ο οντοκεντρικός προγραμματισμός επιτρέπει αποθήκευσει δεδομένων με τις λειτουργίες που μπορεί να κάνει κανείς στα δεδομένα αυτά Ο οντοκεντικός προγραμματισμός είναι ένας πολύ δομημένος τρόπος για επαναχρησιμοποίηση κώδικα Μπορούμε να δημιουργήσουμε πολλά στιγμιότυπα της ίδιας τάξης Όλα είναι τελείως ανεξάρτητα μεταξύ τους