--- language: java contributors: - ["Jake Prather", "http://github.com/JakeHP"] - ["Jakukyo Friel", "http://weakish.github.io"] - ["Madison Dickson", "http://github.com/mix3d"] - ["Simon Morgan", "http://sjm.io/"] - ["Zachary Ferguson", "http://github.com/zfergus2"] - ["Cameron Schermerhorn", "http://github.com/cschermerhorn"] - ["Rachel Stiyer", "https://github.com/rstiyer"] filename: LearnJava.java translators: - ["Andreas Loizou" , "https://github.com/lack3r/"] lang: el-gr --- H Java είναι μία γενικού-σκοπού, συντρέχων (concurrent), βασισμένη σε κλάσεις, αντικειμενοστρεφής (object oriented) γλώσσα προγραμματισμού. [Διαβάστε περισσότερα εδώ.](http://docs.oracle.com/javase/tutorial/java/) ```java // Τα σχόλια μονής γραμμής ξεκινούν με // /* Τα σχόλια πολλών γραμμών μοιάζουν κάπως έτσι. */ /** Τα σχόλια JavaDoc μοιάζουν κάπως έτσι. Χρησιμοποιούνται για να περιγράψουν την Κλάση ή διάφορα χαρακτηριστικά της Κλάσης. */ // Εισαγωγή της κλάσης ArrayList η οποία βρίσκεται εντός του πακέτου java.util import java.util.ArrayList; // Εισαγωγή όλων των κλάσεων που βρίσκονται εντός του πακέτου java.security import java.security.*; // Κάθε αρχείο .java περιέχει μία δημόσια(public) κλάση εξωτερικού-επιπέδου // (outer-level), η οποία έχει το ίδιο ονομα με το αρχείο. public class LearnJava { // Για να τρέξει ένα πρόγραμμα java, πρέπει να έχει μία κύρια μέθοδο (main // method) ως αρχικό σημείο. public static void main (String[] args) { // Χρησιμοποιούμε τη μέθοδο System.out.println() για να τυπώσουμε // γραμμές. System.out.println("Hello World!"); System.out.println( "Integer: " + 10 + " Double: " + 3.14 + " Boolean: " + true); // Για να τυπώσουμε χωρίς να τυπωθεί αλλαγή γραμμής (newline), // χρησιμοποιούμε System.out.print(). System.out.print("Hello "); System.out.print("World"); // Χρησιμοποιούμε τη μέθοδο System.out.printf() για έυκολη μορφοποίηση // της εκτύπωσης. System.out.printf("pi = %.5f", Math.PI); // => pi = 3.14159 /////////////////////////////////////// // Μεταβλητές(Variables) /////////////////////////////////////// /* * Δήλωση Μεταβλητών */ // Δηλώνουμε μία μεταβλητή χρησιμοποιώντας τη μορφή // <Τύπος Μεταβλητής> <Όνομα Μεταβλητής> int fooInt; // Δηλώνουμε πολλαπλές μεταβλητές ίδιου τύπου χρησιμοποιώντας τη μορφή // <Τύπος> <Όνομα1>, <Όνομα2>, <Όνομα3> int fooInt1, fooInt2, fooInt3; /* * Αρχικοποίηση Μεταβλητών */ // Αρχικοποιούμε μια μεταβλητή χρησιμοποιώντας τη μορφή // <τύπος> <όνομα> = <τιμή> int fooInt = 1; // Αρχικοποιούμε πολλαπλές μεταβλητές ιδίου τύπου με την ίδια τιμή // χρησιμοποιώντας <τύπος> <Όνομα1>, <Όνομα2>, <Όνομα3> = <τιμή> int fooInt1, fooInt2, fooInt3; fooInt1 = fooInt2 = fooInt3 = 1; /* * Τύποι μεταβλητών */ // Byte - 8-bit signed two's complement integer // (-128 <= byte <= 127) byte fooByte = 100; // Short - 16-bit signed two's complement integer // (-32,768 <= short <= 32,767) short fooShort = 10000; // Integer - 32-bit signed two's complement integer // (-2,147,483,648 <= int <= 2,147,483,647) int fooInt = 1; // Long - 64-bit signed two's complement integer // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807) long fooLong = 100000L; // Το L χρησιμοποιείται για να δηλώσει ότι η συγκεκριμένη τιμή της // μεταβλητής είναι τύπου Long; // Ό,τιδήποτε χρησιμοποιείται χωρίς αυτό τυχαίνει μεταχείρισης όπως // μία τιμή μεταβλητής integer by default. // Σημείωση: Η Java δεν έχει unsigned τύπους. // Float - Single-precision 32-bit IEEE 754 Floating Point // 2^-149 <= float <= (2-2^-23) * 2^127 float fooFloat = 234.5f; // f or F χρησιμοποιείται για να δηλώσει ότι η συγκεκριμένη τιμή // μεταβλητής είναι τύπου float; // αλλιώς τυγχαίνει μεταχείρισης όπως μία τιμή μεταβλητής double. // Double - Double-precision 64-bit IEEE 754 Floating Point // 2^-1074 <= x <= (2-2^-52) * 2^1023 double fooDouble = 123.4; // Boolean - Αληθής και Ψευδής (true & false) boolean fooBoolean = true; boolean barBoolean = false; // Char - Ένας μόνο χαρακτήρας 16-bit Unicode char fooChar = 'A'; // Οι μεταβλητές final δεν μπορούν να ανατεθούν ξανά σε άλλο // αντικείμενο, final int HOURS_I_WORK_PER_WEEK = 9001; // αλλά μπορούν να αρχικοποιηθούν αργότερα. final double E; E = 2.71828; // BigInteger - Immutable αυθαίρετης-ακρίβειας ακέραιος // // Ο BigInteger είναι ένας τύπος δεδομένων ο οποίος επιτρέπει στους // προγραμματιστές να χειρίζονται ακέραιους μεγαλύτερους από 64-bits. // Οι ακέραιοι αποθηκεύονται ως πίνακας από bytes και τυχαίνουν // επεξεργασίας χρησιμοποιώντας συναρτήσεις εσωματωμένες στην κλάση // BigInteger // Ένας BigInteger μπορεί να αρχικοποιηθεί χρησιμοποιώντας ένα πίνακα // από bytes ή γραμματοσειρά (string). BigInteger fooBigInteger = new BigInteger(fooByteArray); // BigDecimal - Immutable, αυθαίρετης-ακρίβειας, εμπρόσημος (signed) // δεκαδικός αριθμός // // Ένας BigDecimal παίρνει δύο μέρη: Μία αυθαίρετης ακρίβειας, // ακέραια, unscaled τιμή και μία κλιμάκωση(scale) ως ένα 32-bit // ακέραιο (integer). // // Ο BigDecimal επιτρέπει στον προγραμματιστή να έχει πλήρη έλεγχο // όσον αφορά τη δεκαδική στρογγυλοποίηση (rounding). Προτείνεται η // χρήση του BigDecimal με τιμές νομισμάτων και όπου απαιτείται η // ακριβής δεκαδική ακρίβεια. // // Ο BigDecimal μπορεί να αρχικοποιηθεί με int, long, double ή String // ή με την αρχικοποίηση της unscaled τιμής (BigInteger) και της // κλίμακας (scale) (int). BigDecimal fooBigDecimal = new BigDecimal(fooBigInteger, fooInt); // Χρειάζεται να είμαστε προσεκτικοί με τον κατασκευαστή (constructor) // ο οποίος παίρνει float ή double καθώς η ανακρίβεια του float/double // θα αντιγραφεί στον BigDecimal. // Είναι προτιμότερο να χρησιμοποιείται ο κατασκευαστής String (String // constructor) όταν χρειάζεται ακριβής τιμή. BigDecimal tenCents = new BigDecimal("0.1"); // Strings - Γραμματοσειρές String fooString = "My String Is Here!"; // Ο χαρακτήρας \n είναι ένας χαρακτήρας διαφυγής (escaped character) // ο οποίος ξεκινά μία νέα γραμμή String barString = "Printing on a new line?\nNo Problem!"; // Ο χαρακτήρας \t είναι ένας χαρακτήρας διαφυγής (escaped character) // ο οποίος προσθέτει ένα χαρακτήρα tab String bazString = "Do you want to add a tab?\tNo Problem!"; System.out.println(fooString); System.out.println(barString); System.out.println(bazString); // Πίνακες (Arrays) // Το μέγεθος του πίνακα πρέπει να αποφασιστεί με την αρχικοποίηση του // πίνακα // Οι ακόλουθες μορφές μπορούν να χρησιμοποιηθούν για την δήλωση ενός // πίνακα // <Τυπος δεδομένων>[] <Όνομα Μεταβλητής> = new <Τύπος Δεδομένων>[<μέγεθος πίνακα>]; // <Τυπος δεδομένων> <Όνομα Μεταβλητής>[] = new <Τυπος δεδομένων>[<μέγεθος πίνακα>]; int[] intArray = new int[10]; String[] stringArray = new String[1]; boolean boolArray[] = new boolean[100]; // Ακόμη ένας τρόπος για να δηλώσεις (to declare) και να // αρχικοποιήσεις ένα πίνακα int[] y = {9000, 1000, 1337}; String names[] = {"Bob", "John", "Fred", "Juan Pedro"}; boolean bools[] = new boolean[] {true, false, false}; // Ευρετηρίαση (indexing) ενός πίνακα - Πρόσβαση (accessing) ενός // στοιχείου System.out.println("intArray @ 0: " + intArray[0]); // Οι πίνακες ξεκινούν από το μηδέν (zero-indexed) και είναι ευμετάβλητοι (mutable). intArray[1] = 1; System.out.println("intArray @ 1: " + intArray[1]); // => 1 // Παρόμοια // ArrayLists - Παρόμοιοι με τους πίνακες με τη διαφορά ότι προσφέρουν // περισσότερη λειτουργικότητα και το μέγεθος είναι ευμετάβλητο // (mutable). // LinkedLists - Υλοποίηση διπλά-συνδεδεμένης λίστας(doubly-linked // list). Όλες οι λειτουργίες εκτελώνται όπως αναμένεται σε μία διπλά // συνδεδεμένη (doubly-linked) λίστα. // Maps - Ένα σύνολο αντικειμένων τα οποία συνδέου (map) κλειδιά (keys) // σε τιμές (values). Ο Map είναι διεπαφή (interface) και συνεπώς δεν // μπορεί να συγκεκριμενοποίηθεί (instantiated). // Ο τύπος των κλειδιών και των τιμών τα οποία συμπεριλαμβάνονται σε // ένα Map πρέπει να καθοριστεί κατά τη διάρκεια της // συγκεκριμενοποίησης (instantiation) της κλάσης που υλοποιεί τη // διεπαφή Map. Κάθε κλειδί (key) μπορεί να συνδεθεί (map) σε μόνο μία // αντίστοιχη τιμή και κάθε κλειδί μπορεί να εμφανιστεί μόνο μία φορά // (no duplicates). // HashMaps - Η κλάση αυτή χρησιμοποιεί ένα πίνακα-κατακερματισμού // (hashtable) για να υλοποιήσει τη διεπαφή Map. Αυτό επιτρέπει το // χρόνο εκτέλεσης βασικών λειτουργιών, όπως της get και insert // στοιχείου να παραμείνει σταθερός (constant) ακόμη και για μεγάλα // σύνολα (sets.) /////////////////////////////////////// // Τελεστές (Operators) /////////////////////////////////////// System.out.println("\n->Operators"); int i1 = 1, i2 = 2; // Συντομογραφία για πολλαπλές δηλώσεις // Οι αριθμητικοί τελεστές είναι απλοί System.out.println("1+2 = " + (i1 + i2)); // => 3 System.out.println("2-1 = " + (i2 - i1)); // => 1 System.out.println("2*1 = " + (i2 * i1)); // => 2 System.out.println("1/2 = " + (i1 / i2)); // => 0 (int/int returns int) System.out.println("1/2 = " + (i1 / (double)i2)); // => 0.5 // Υπόλοιπο (Modulo) System.out.println("11%3 = "+(11 % 3)); // => 2 // Τελεστές σύγκρισης System.out.println("3 == 2? " + (3 == 2)); // => false System.out.println("3 != 2? " + (3 != 2)); // => true System.out.println("3 > 2? " + (3 > 2)); // => true System.out.println("3 < 2? " + (3 < 2)); // => false System.out.println("2 <= 2? " + (2 <= 2)); // => true System.out.println("2 >= 2? " + (2 >= 2)); // => true // Λογικοί Τελεστές (Boolean) System.out.println("3 > 2 && 2 > 3? " + ((3 > 2) && (2 > 3))); // => false System.out.println("3 > 2 || 2 > 3? " + ((3 > 2) || (2 > 3))); // => true System.out.println("!(3 == 2)? " + (!(3 == 2))); // => true // Τελεστές πράξεων με bits (Bitwise)! /* ~ bitwise τελεστής μοναδιαίου συμπληρώματος (Unary bitwise complement) << Προσημασμένη ολίσθηση αριστερά (Signed left shift) >> Προσημασμένη/Αριθμητική ολίσθηση Δεξιά (Signed/Arithmetic right shift) >>> Μη προσημασμένη/Λογική ολίσθηση δεξιά (Unsigned/Logical right shift) & Διαδικός τελεστής AND (Bitwise AND) ^ Διαδικός τελεστής XOR (Bitwise exclusive OR) | Διαδικός τελεστής OR (Bitwise inclusive OR) */ // Αυξητικοί τελεστές int i = 0; System.out.println("\n->Inc/Dec-rementation"); // Οι τελεστές ++ και -- μειώνουν και αυξάνουν κατά 1 αντίστοιχα. // Εάν τοποθετητούν πριν τη μεταβλητή, αυξάνουν και μετά επιστρέφουν. // Μετά τη μεταβλητή επιστρέφουν και μετά αυξάνουν. System.out.println(i++); // i = 1, τυπώνει 0 (post-increment) System.out.println(++i); // i = 2, τυπώνει 2 (pre-increment) System.out.println(i--); // i = 1, τυπώνει 2 (post-decrement) System.out.println(--i); // i = 0, τυπώνει 0 (pre-decrement) /////////////////////////////////////// // Δομές ελέγχου (Control Structures) /////////////////////////////////////// System.out.println("\n->Control Structures"); // Οι δηλώσεις If είναι c-like int j = 10; if (j == 10) { System.out.println("I get printed"); } else if (j > 10) { System.out.println("I don't"); } else { System.out.println("I also don't"); } // Επανάληψη While (While loop) int fooWhile = 0; while(fooWhile < 100) { System.out.println(fooWhile); // Άυξησε τον μετρητή // Επανάλαβε 100 φορές, fooWhile 0,1,2...99 fooWhile++; } System.out.println("fooWhile Value: " + fooWhile); // Επανάληψη Do While (Do While Loop) int fooDoWhile = 0; do { System.out.println(fooDoWhile); // Άυξησε το μετρητή(counter) // Επανάλαβε 99 times, fooDoWhile 0->99 fooDoWhile++; } while(fooDoWhile < 100); System.out.println("fooDoWhile Value: " + fooDoWhile); // Επανάληψη For (For Loop) // Δομή επανάληψης for => // for(<Αρχική Δήλωση>; <προυπόθεση (conditional)>; <βήμα (step)>) for (int fooFor = 0; fooFor < 10; fooFor++) { System.out.println(fooFor); // Iterated 10 times, fooFor 0->9 } System.out.println("fooFor Value: " + fooFor); // Έξοδος από εμφωλευμένη (nested) επανάληψη For με ετικέττα (Label) outer: for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { if (i == 5 && j ==5) { break outer; // δραπετεύει εκτός της εξωτερικής(outer) επανάληψης αντί μόνο της εσωτερικής } } } // Επανάληψη For Each // Η επανάληψη for είναι επίσης ικανή να επαναλαμβάνεται τόσο σε // πίνακες όσο και σε αντικείμενα τα οποία υλοποιούν τη διεπαφή // Iterable. int[] fooList = {1, 2, 3, 4, 5, 6, 7, 8, 9}; // Σύνταξη της επανάληψης for each => for (<αντικείμενο> : ) // Διαβάζεται ως: Για κάθε αντικείμενο στο iterable // Σημείωση: ο τύπος του αντικειμένου πρέπει να τεριάζει με τον τύπο του στοιχείου του iterable. for (int bar : fooList) { System.out.println(bar); //Επαναλαμβάνεται 9 φορές και τυπώνει 1-9 σε καινούριες γραμμές } // Switch Case // Ένα switch δουλέυει με byte, short, char, και int τύπους δεδομένων. // Δουλέυει επίσης με τύπους enumerated (Συζήτηση στους τύπους Enum), // τη κλάση String, και μερικές ειδικές περιπτώσεις οι οποίες // περιλαμβάνουν primitive τύπους: Character, Byte, Short, and Integer. int month = 3; String monthString; switch (month) { case 1: monthString = "January"; break; case 2: monthString = "February"; break; case 3: monthString = "March"; break; default: monthString = "Some other month"; break; } System.out.println("Switch Case Result: " + monthString); // Αρχίζοντας από τη Java 7, switching για Strings δουλεύει έτσι: String myAnswer = "maybe"; switch(myAnswer) { case "yes": System.out.println("You answered yes."); break; case "no": System.out.println("You answered no."); break; case "maybe": System.out.println("You answered maybe."); break; default: System.out.println("You answered " + myAnswer); break; } // Συντομογραφία του Conditional // Μπορείς να χρησιμοποιήσεις τον τελεστή '?' για γρήγορες αναθέσεις ή // logic forks. Διαβάζεται ως "Αν η (πρόταση) είναι αληθής, // χρησιμοποίησε <την πρώτη τιμή>, αλλιώς, χρησιμοποία <την δεύτερη // τιμή>" int foo = 5; String bar = (foo < 10) ? "A" : "B"; System.out.println(bar); // Prints A, because the statement is true //////////////////////////////////////// // Μετατροπή Τύπων Δεδομένων και Typecasting //////////////////////////////////////// // Μετατροπή δεδομένων // Μετατροπή από String σε Integer Integer.parseInt("123");//returns an integer version of "123" // Μετατροπή από Integer σε String Integer.toString(123);//returns a string version of 123 // Για άλλες μετατροπές δες τις ακόλουθες κλάσεις: // Double // Long // String // Typecasting // Μπορείς επίσης να κάνεις cast αντικείμενα Java. Υπάρχουν πολλές // λεπτομέρειες και μερικές πραγματεύονται κάποιες πιο προχωρημένες // ένοιες. Για δες εδώ: // http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html /////////////////////////////////////// // Κλάσεις και Συναρτήσεις /////////////////////////////////////// System.out.println("\n->Classes & Functions"); // (Ο ορισμός της κλάσης Bicycle ακολουθεί) // Χρησιμοποία το new για να δημιουργήσεις ένα αντικείμενο μίας κλάσης Bicycle trek = new Bicycle(); // Κλήση μεθόδων του αντικειμένου trek.speedUp(3); // Πάντοτε πρέπει να χρησιμοποιείς μεθόδους setter // και getter trek.setCadence(100); // Το toString επιστρέφει την αναπαράσταση σε String μορφή του // αντικειμένου αυτού. System.out.println("trek info: " + trek.toString()); // Double Brace Initialization // Η Γλώσσα Java δεν έχει σύνταξη για το πως να δημιουργήσεις static // Collections με κάποιο εύκολο τρόπο. Συνήθως θα το κάνεις αυτό με // τον παρακάτω τρόπο: private static final Set COUNTRIES = new HashSet(); static { validCodes.add("DENMARK"); validCodes.add("SWEDEN"); validCodes.add("FINLAND"); } // Αλλά υπάρχει ένας κομψός τρόπος να επιτύχεις το ίδιο πράγμα // ευκολότερα, χρησιμοποιώντας κάτι το οποίο λέγεται Double Brace // Initialization. private static final Set COUNTRIES = new HashSet() {{ add("DENMARK"); add("SWEDEN"); add("FINLAND"); }} // Η πρώτη αγκύλη δημιουργεί μία νέα AnonymousInnerClass και η // δεύτερη δηλώνει ένα instance initializer block. Το block // καλείται όταν η ανώνυμη εσωτερική κλάση δημιουργηθεί. // Η μέθοδος αύτή δεν δουλεύει μόνο για τις Collections, αλλά για όλες // τις non-final κλάσεις. } // Τέλος μεθόδου main } // Τέλος κλάσης LearnJava // Μπορείς να κάνεις include άλλες, όχι-δημόσιες (non-public) // εξωτερικού-επιπέδου (outer-level) κλάσεις σε ένα αρχείο .java, αλλά δεν // είναι καλή πρακτική. Αντί αυτού, διαχώρησε τις κλάσεις σε ξεχωριστά αρχεία. // Σύνταξη Δήλωσης Κλάσης (Class Declaration Syntax): // class { // // Συμπεριλαμβάνονται πεδία δεδομένων (data fields), κατασκευαστές (constructors), συναρτήσεις (functions) . // // Οι συναρτήσεις ονομάζονται "μεθόδοι" στη Java. // } class Bicycle { // Πεδία/μεταβλητές της Κλάσης Bicycle // Public(Δημόσιες): Μπορούν να γίνουν προσβάσιμες από παντού public int cadence; // Private(Ιδιωτικές): Προσβάσιμες μόνο εντός της κλάσης private int speed; // Protected(Προστατευμένες): Προσβάσιμες από την κλάση και τις υποκλάσεις (subclasses) της protected int gear; String name; // Προκαθορισμένο: Προσβάσιμη μόνο εντός του πακέτου static String className; // Static μεταβλητή κλάσης // Static block // H Java δεν υποστηρίζει υλοποίησεις στατικών κατασκευαστών (static // constructors), αλλά έχει ένα static block το οποίο μπορεί να // χρησιμοποιηθεί για να αρχικοποιήσει στατικές μεταβλητές (static // variables). Το block αυτό θα καλεσθεί όταν η κλάση φορτωθεί. static { className = "Bicycle"; } // Οι κατασκευαστές (constructors) είναι ένας τρόπος για δημιουργία κλάσεων // Αυτός είναι ένας κατασκευαστής (constructor) public Bicycle() { // Μπορείς επίσης να καλέσεις άλλο κατασκευαστή: // this(1, 50, 5, "Bontrager"); gear = 1; cadence = 50; speed = 5; name = "Bontrager"; } // Αυτός είναι ένας κατασκευαστής ο οποίος δέχεται arguments public Bicycle(int startCadence, int startSpeed, int startGear, String name) { this.gear = startGear; this.cadence = startCadence; this.speed = startSpeed; this.name = name; } // Οι μεθόδοι (Methods) συντάσσονται ως ακολούθως: // <όνομα μεθόδου>() // Οι κλάσεις Java συχνά υλοποιούν getters and setters for their fields // Σύνταξη δήλωσης μεθόδου: // <Προσδιοριστές πρόσβασης> <τύπος επιστροφής> <όνομα μεθόδου>() public int getCadence() { return cadence; } // Οι μεθόδοι void δεν απαιτούν return statement public void setCadence(int newValue) { cadence = newValue; } public void setGear(int newValue) { gear = newValue; } public void speedUp(int increment) { speed += increment; } public void slowDown(int decrement) { speed -= decrement; } public void setName(String newName) { name = newName; } public String getName() { return name; } //Μέθοδος η οποία επιστρέφει ως String τις τιμές των χαρακτηριστικών του // αντικειμένου. @Override // Χρησιμοποιείται, καθώς η συγκεκριμένη μέθοδος κληρονομήθηκε από τη κλάση Object. public String toString() { return "gear: " + gear + " cadence: " + cadence + " speed: " + speed + " name: " + name; } } // Τέλος κλάσης Bicycle // Η PennyFarthing είναι υποκλάση της Bicycle class PennyFarthing extends Bicycle { // (Tα Penny Farthings είναι τα ποδήλατα με τον μεγάλο μπροστινό τροχό. // Δεν έχουν ταχύτητες.) public PennyFarthing(int startCadence, int startSpeed) { // Κάλεσε τον parent constructor χρησιμοποιώντας το super super(startCadence, startSpeed, 0, "PennyFarthing"); } // Χρειάζεται να μαρκάρεις τη μέθοδο την οποία κάνεις overriding // χρησιμοποιώντας ένα @annotation. // Για να μάθεις περισσότερα σχετικά με το τι είναι οι επισημάνσεις // (annotations) και τον σκοπό τους δες αυτό: // http://docs.oracle.com/javase/tutorial/java/annotations/ @Override public void setGear(int gear) { gear = 0; } } // Διεπαφές (Interfaces) // Σύνταξη δήλωσης διεπαφής // interface extends { // // Σταθερές (Constants) // // Δηλώσεις Μεθόδων (Method declarations) // } // Παράδειγμα - Food: public interface Edible { public void eat(); // Κάθε κλάση η οποία υλοποιεί τη διεπαφή αυτή πρέπει // να υλοποιήσει τη συγκεκριμένη μέθοδο. } public interface Digestible { public void digest(); } // Μπορούμε να δημιουργήσουμε μία κλάση η οποία υλοποιεί και τις δύο αυτές διεπαφές. public class Fruit implements Edible, Digestible { @Override public void eat() { // ... } @Override public void digest() { // ... } } // Στην Java, μπορείς να κληρονομήσεις (extend) από μόνο μία κλάση, // αλλά μπορείς να υλοποιήσεις πολλές διεπαφές. Για παράδειγμα: public class ExampleClass extends ExampleClassParent implements InterfaceOne, InterfaceTwo { @Override public void InterfaceOneMethod() { } @Override public void InterfaceTwoMethod() { } } // Abstract (Αφηρημένες) Κλάσεις // Σύνταξη Δήλωσης Abstract Κλάσης // abstract extends { // // Σταθερές και μεταβλητές // // Δηλώσεις μεθόδων // } // Μαρκάροντας μία κλάση ως abstract σημαίνει ότι περιέχει abstract μεθόδους // οι οποίες πρέπει να οριστούν σε μία κλάση παιδί (child class). // Παρόμοια με τις διεπαφές (interfaces), οι abstract κλάσεις δεν μπορούν να // γίνουν instantiated, αλλά αντί αυτού πρέπει να γίνει extend και οι abstract // μεθόδοι πρέπει να οριστούν. Διαφορετικά από τις Διεπαφές, οι abstract // κλάσεις μπορούν να περιέχουν τόσο υλοποιημένες όσο και abstract μεθόδους. // Οι μεθόδοι σε μια Διεπαφή δεν μπορούν να έχουν σώμα (δεν είναι υλοποιημένες // δηλαδή εκτός εάν η μέθοδος είναι στατική και οι μεταβλητές είναι final by // default αντίθετα απο μία abstract κλάση. Επίσης, οι abstract κλάσεις // ΜΠΟΡΟΥΝ να έχουν την μέθοδο "main". public abstract class Animal { public abstract void makeSound(); // Οι μεθόδοι μπορούν να έχουν σώμα (body) public void eat() { System.out.println("I am an animal and I am Eating."); // Σημείωση: Μπορούμε να έχουμε πρόσβαση σε ιδιωτικές (private) μεταβλητές εδώ. age = 30; } // Δεν χρειάζεται να αρχικοποιηθεί, εντούτοις σε ένα interface μία // μεταβλητή είναι implicitly final και έτσι χρειάζεται να αρχικοποιηθεί protected int age; public void printAge() { System.out.println(age); } // Οι Abstract κλάσεις μπορούν να έχουν συνάρτηση main. public static void main(String[] args) { System.out.println("I am abstract"); } } class Dog extends Animal { // Σημείωση ότι χρειάζεται να κάνουμε override τις abstract μεθόδους στην // abstract κλάση. @Override public void makeSound() { System.out.println("Bark"); // age = 30; ==> ERROR! Το πεδίο age είναι private στο Animal } // ΣΗΜΕΙΩΣΗ: Θα πάρεις error εάν χρησιμοποίησεις το // @Override annotation εδώ, καθώς η java δεν επιτρέπει // να γίνονται override οι static μεθόδοι. // Αυτό που γίνεται εδώ ονομάζεται METHOD HIDING. // Για δες αυτό το εξαιρετικό ποστ στο SO (Stack Overflow): http://stackoverflow.com/questions/16313649/ public static void main(String[] args) { Dog pluto = new Dog(); pluto.makeSound(); pluto.eat(); pluto.printAge(); } } // Κλάσεις Final // Σύνταξη δήλωσης μίας Final κλάσης // final { // // Σταθερές και μεταβλητές // // Δήλωση μεθόδων // } // Οι κλάσεις Final είναι κλάσεις οι οποίες δεν μπορούν να κληρονομηθούν και // συνεπώς είναι final child. In a way, final classes are the opposite of // abstract classes because abstract classes must be extended, but final // classes cannot be extended. public final class SaberToothedCat extends Animal { // Σημείωση ότι χρειάζεται και πάλι να κάνουμε override τις abstract // μεθόδους στην abstract κλάση. @Override public void makeSound() { System.out.println("Roar"); } } // Τελικές (Final) μεθόδοι public abstract class Mammal() { // Σύνταξη μίας Final μεθόδου: // <Προσδιοριστής πρόσβασης (access modifier)> final <τύπος επιστροφής> <Όνομα μεθόδου>() // Οι Final μεθόδοι, όπως και οι final κλάσεις δεν μπορούν να γίνουν // overridden από κλάση παιδί, // και είναι συνεπώς η τελική υλοποίηση της μεθόδου. public final boolean isWarmBlooded() { return true; } } // Τύποι Enum // // Ένας τύπος enum είναι ένας ειδικός τύπος δεδομένων, ο οποίος επιτρέπει σε // μια μεταβλητή να είναι ένα σύνολο από προκαθορισμένες σταθερές. Η μεταβλητή // πρέπει να είναι ίση με μία από τις τιμές αυτές που έχουν προκαθοριστεί. // Επειδή είναι σταθερές, τα ονόματα ενός enum πεδίου γράφονται με κεφαλαίους // χαρακτήρες. Στην γλώσσα προγραμματισμού Java, ορίζεις ένα τύπο enum // χρησιμοποιώντας τη δεσμευμένη λέξη enum. Για παράδειγμα, θα μπορούσες να // καθορίσεις ένα τύπο enum με όνομα days-of-the-week ως: public enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY } // Μπορούμε να χρησιμοποιήσουμε τον enum Day όπως παρακάτω: public class EnumTest { // Μεταβλητή Enum Day day; public EnumTest(Day day) { this.day = day; } public void tellItLikeItIs() { switch (day) { case MONDAY: System.out.println("Mondays are bad."); break; case FRIDAY: System.out.println("Fridays are better."); break; case SATURDAY: case SUNDAY: System.out.println("Weekends are best."); break; default: System.out.println("Midweek days are so-so."); break; } } public static void main(String[] args) { EnumTest firstDay = new EnumTest(Day.MONDAY); firstDay.tellItLikeItIs(); // => Mondays are bad. EnumTest thirdDay = new EnumTest(Day.WEDNESDAY); thirdDay.tellItLikeItIs(); // => Midweek days are so-so. } } // Οι τύποι Enum είναι πολύ πιο δυνατοί από όσο έχουμε δείξει πιο πάνω. // Το σώμα του enum (enum body) μπορεί να περιέχει μεθόδους και άλλα πεδία. // Μπορείς να δεις περισσότερα στο // https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html ``` ## Επιπλέων διάβασμα Οι σύνδεσμοι που παρέχονται εδώ είναι απλά για να κατανοήσεις περισσότερο το θέμα. Σε προτρύνουμε να ψάξεις στο Google και να βρεις συγκεκριμένα παραδείγματα. **Eπίσημοι Οδηγοί της Oracle**: * [Φροντιστήριο εκμάθησης Java από τη Sun / Oracle](http://docs.oracle.com/javase/tutorial/index.html) * [Τροποποιητές επιπέδου πρόσβασης(Access level modifiers) Java](http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html) * [Έννοιες αντικειμενοστραφούς (Object-Oriented) προγραμματισμού](http://docs.oracle.com/javase/tutorial/java/concepts/index.html): * [Κληρονομικότητα (Inheritance)](http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html) * [Πολυμορφισμός (Polymorphism)](http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html) * [Αφαιρετικότητα (Abstraction)](http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html) * [Εξαιρέσεις (Exceptions)](http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html) * [Διεπαφές (Interfaces)](http://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html) * [Generics](http://docs.oracle.com/javase/tutorial/java/generics/index.html) * [Συμβάσεις κώδικα Java (Code Conventions)](http://www.oracle.com/technetwork/java/codeconvtoc-136057.html) **Πρακτικές και Φροντιστήρια Online** * [Learneroo.com - Μάθε Java](http://www.learneroo.com) * [Codingbat.com](http://codingbat.com/java) **Βιβλία**: * [Head First Java](http://www.headfirstlabs.com/books/hfjava/) * [Thinking in Java](http://www.mindview.net/Books/TIJ/) * [Objects First with Java](http://www.amazon.com/Objects-First-Java-Practical-Introduction/dp/0132492660) * [Java The Complete Reference](http://www.amazon.com/gp/product/0071606300)