Θεωρώ ότι είναι μια από τις πιο απλές γλώσσες, είναι ιδανική για αρχάριους και πολύ εύκολη στην εκμάθηση σε όσους γνωρίζουν java (ναι java!).
O λόγος είναι ότι αν εξεραίσουμε το συντακτικό της γλώσσας οι θεμελιώδης έννοιες θυμίζουν πολύ java. Ιστορικά βέβαια η Java θυμίζει Objective-C μιας και η δεύτερη προυπήρχε.
Ο Patrick Naughton ο πατέρας της Java λάτρευε την Objective-C της τότε NeXT και μισούσε την C++. Μάλιστα ήθελε να φύγει από τη SUN και να πάει να δουλέψει στη NeXT, ευτυχώς για αυτόν που δε το έκανε μιας και θα ήταν σύντομα άνεργος! Πολλοί άνθρωποι της NeXT επίσης μετά το κλείσιμο της εταιρίας πήγαν και δούλεψαν με τον Naughton και μετέφεραν τεχνολογίες της Ojb-C όπως τα protocols στην Java (interfaces).
Αυτό που τρομάζει κάποιον που πρωτοβλέπει Obj-C είναι η λίγο περίεργη σύνταξη της. Βασικά η Obj-C είναι gcc + NeXT object oriented extentions. Μπορούμε δηλαδή να γράψουμε κανονικά C σαν να γράφαμε για το Linux μιας και compiler είναι ο ίδιος ακριβώς. Από τη στιγμή όμως που θελήσουμε να χρησιμοποίσουμε τα extentions αλλάζουμε λίγο φιλοσοφία.
Μη τρομάζετε όμως γιατί είναι ΠΟΛΥ απλά τα πράγματα.
Εν αρχή είναι η κλάση. Ο ορισμός της κλάσης και το implementation της κλάσης. Το Xcode θέλει να σπάει μια κλάση σε δύο αρχεία. Στο header file(.h) που γίνεται ο ορισμός και στο implementation(.m) που είναι το.... implementation:)
Ας δούμε ένα header file μιας κλάσης που θα χρησιμοποιήσουμε αργότερα στο παχνίδι μας. Φυσικά δε το βάζω όλο μιας και δε χρειάζεται να λιώσουμε στα listings ακόμα:)
// TestView.h
// Deflector
//
// Created by Antony Mavrelos (aka Shock) on 23/01/2009.
//
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import "LazerBeamsLayerDelegate.h"
int beamColour[10][300];
int layerX[300];
int layerY[300];
int initialTileCoordX[300];
int initialTileCoordY[300];
int tileAngle[300];
int lazerCount;
int lazerOutX[10];
int lazerOutY[10];
int lazerPosInMap[10];
BOOL lazerOnOff[10];
int lazerAngle[10];
BOOL levelComplete;
CALayer* tileLayer[300];
@interface TestView : UIScrollView {
int lazerLayerWidth;
int lazerLayerHeight;
LazerBeamsLayerDelegate* lazerLayerDelegate;
CALayer* rootLayer;
int lazer0x, lazer0y;
CGPoint firstTouch;
CGPoint currentTouchPosition;
CGPoint scoreLayerCoordinates;
CGRect visibleRect;
BOOL levelIsDrawn;
BOOL rottorIsVisible;
BOOL firstGate;
NSInteger levelNum;
NSUInteger tapCount;
UIImage* image;
CGImageRef mirrorImageRef;
//μπλα μπλα μπλα
UITouch* touch;
int blockMask[320][30];
//μπλα μπλα μπλα
}
@property CGPoint firstTouch;
@property CGPoint currentTouchPosition;
@property CGPoint scoreLayerCoordinates;
@property CGRect visibleRect;
@property NSInteger levelNum;
@property BOOL levelIsDrawn;
@property BOOL rottorIsVisible;
- (void)rotateTile:(int)tID:(float)degree:(BOOL)setuplayers;
@end
Αυτό που μας ενδιαφέρει εδώ είναι το block
@interface TestView : UIScrollView {
//.....
@end
Αυτός είναι και ο ορισμός της κλάσης η οποία ονομάζεται TestView και κληρονομεί τις ιδιότητες της UIScrollView κλασης. Αν θέλουμε να το πάμε παραπέρα μπορούμε να ανατρέξουμε στο documentation στο XCode και να δούμε ότι και αυτή είναι παιδί της UIView και πάει λέγοντας.
Αρα με το "@interface" (σας θυμίζει τίποτα το @?:)) ξεκινάμε τη δήλωση ακολουθούμενο από το όνομα την άνω και κάτω τελεία και τον πατέρα.
Στην Obj-C όπως και στην Java δεν μπορούμε να έχουμε πολλούς πατεράδες.
Τώρα ότι βρίσκεται ανάμεσα στο @interface και @end είναι οι instance variables. Άφησα μερικές για δείγμα για να δείξω ότι μπορούμε να έχουμε κλασσικά C primitive types αλλά και άλλα αντικείμενα δικά μας (LazerBeamsLayerDelegate) ή κλασεις συστήματος όπως η UITouch.
Μιας και το έφερε η κουβέντα να πούμε ότι όταν δηλώνουμε μια μεταβλητή τύπου object πάντα μιλάμε για έναν pointer. Τα objects δεν είναι τίποτα περισσότερο από θέσεις μνήμης.
Όλες οι NSκάτι, UIκάτι κλάσεις του συστήματος χρειάζονται και το αγαπημένο μας αστεράκι:)
Π.χ UIImage* image;
Εξαίρεση αποτελεί η NSInteger η οποία βασικά είναι ένας απλός wrapper.
Αν αναρωτιέστε τι παίζει με τα CGPoint, CGRect και δεν είναι pointers η απάντηση είναι απλή, αυτές είναι structures.
Μια σύνηθες τακτική όταν γράφουμε κώδικα είναι να χρησιμοποιούμε geters και seters για τις protected μεταβλητές μας. Χωρίς να μπλέξουμε το scope των μεταβλητών στην όλη φάση και για να απλοποιήσουμε τα πράγματα να πούμε ότι το ίδιο σκεπτικό υπάρχει και εδώ αλλά με μια διαφορά. Η obj-c σου δίνει τη δυνατότητα να φτιάξεις accessors χωρίς κώδικα (τουλάχιστον όχι και τόσο γράψιμο).
Το @property κάνει αυτή ακριβώς τη δουλειά. Δηλώνουμε τη πρόθεση μας να φτιαχτούν εσωτερικά δύο μέθοδοι που μπορούμε να χρησιμοποιούμε στον κώδικα μας. Λέω "δηλώνουμε την πρόθεση μας" γιατί η πραγματική υλοποίηση γίνεται στο implementation με την @synthesize που θα δούμε αργότερα.
Η μια μέθοδος λοιπόν που φτιάχνει η Obj-C έχει το όνομα της μεταβλητής και είναι η *get* μέθοδος και η άλλη είναι η set+;"όνομα μεταβλητής".
Για παράδειγμα στην levelIsDrawn μεταβλητή θα φτιαχτει μια μέθοδος levelIsDrawn() που θα επιστρέφει BOOL και μια setlevelIsDrawn(BOOL) που θα δέχεται σαν όρισμα μια Bool τιμή, η οποία μιας και το έφερε η κουβέντα είναι YES ή NO.
Αντί για TRUE/FALSE έχουμε YES/NO, εύκολο και κατανοητό.
Στην γραμμή 61 βλέπουμε τον ορισμό μιας μεθόδου. Το "-" στην αρχή δηλώνει ότι αυτή είναι μια Instance method. Αν είχε (+) θα ήταν ο ορισμός μιας class method. Ακριβώς μετά μέσα σε παρενθέσεις είναι η επιστροφή της μεθόδου.
Ακολουθεί το όνομα και αν υπάρχουν παράμετροι τις ξεχωρίζουμε με άνω και κάτω τελείες
- (void) rotateTile :(int)tID :(float)degree:(BOOL)setuplayers;
Άρα έχουμε "instance/class sign" (return type) method name :type par1 : type par1 : type par2
Φαίνεται λίγο περίεργο για αρχή αλλά συνηθίζεται εύκολα.
0 σχόλια:
Post a Comment