Δημιουργία κλάσεων

Διομήδης Σπινέλλης
Τμήμα Διοικητικής Επιστήμης και Τεχνολογίας
Οικονομικό Πανεπιστήμιο Αθηνών
dds@aueb.gr

Ορισμός κλάσεων

Ορισμός πεδίων υπόστασης

Ορισμός μεθόδων υπόστασης

Πρόσβαση στα μέλη της κλάσης

Πρόσβαση στα μέλη της κλάσης: παράδειγμα

Μέθοδοι κατασκευής

Μέθοδοι κατασκευής: παράδειγμα

class Point {
    /* Fields */

    /** Point x coordinate */
    private int x;
    /** Point y coordinate */
    private int y;

    /* Methods */
    /** Default constructor */
    Point() { x = y = 0; }
    /** Constructor with coordinates */
    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

Έλεγχος πρόσβασης

Κάθε μέθοδος ή πεδίο μπορεί να έχει ως προσδιοριστή
public
Το μέλος είναι ορατό σε όλες τις άλλες κλάσεις
private
Το μέλος είναι ορατό μόνο στις μεθόδους της δικής μας κλάσης
(τίποτα)
Το μέλος είναι ορατό στις κλάσεις του πακέτου μας
Μια καλοσχεδιασμένη κλάση έχει:

Ορισμός ιδιοτήτων και μεθόδων κλάσης

Παράδειγμα ιδιοτήτων και μεθόδων κλάσης

Μπλοκ αρχικοποίησης

Σε ανώνυμα μπλοκ { } στο σώμα της κλάσης μπορεί να τοποθετηθεί:

Εσωτερικές κλάσεις

Μια κλάση μπορεί να οριστεί εσωτερικά:

Παράδειγμα εσωτερικής κλάσης

class Rectangle {
    private static class Point {
        private int x, y;

        /** Point constructor */
        Point(int ix, int iy) {
            x = ix;
            y = iy;
        }
    }

    private Point topLeft, bottomRight;

    /** Rectangle constructor */
    Rectangle(int x, int y, int height, int width) {
        topLeft = new Point(x, y);
        bottomRight = new Point(x + width, y + height);
    }
}

Παράδειγμα ανώνυμης κλάσης

class InnerCall {
    public static void main(String args[]) {
        System.out.println(new Object());
        System.out.println(new Object() {
            @Override
            public String toString() {
                return "I am a woke object";
            }
        });
    }
}

Απαριθμήσεις

Παράδειγμα

enum Ingredients {
  TOMATO,
  ONION,
  TZATZIKI,
  POTATO,
  MUSTARD,
  SOUVLAKI,
  GYROS
};

Χρήση απαριθμήσεων

Απαρίθμηση ως κλάση

Η αντίστοιχη κλάση χωρίς τη χρήση απαρίθμησης θα είχε την παρακάτω μορφή.

public class Ingredients {
    // Static array to hold all ingredient constants
    private static final Ingredients[] VALUES = new Ingredients[7];

    // Constants with names and ordinal values
    public static final Ingredients TOMATO = new Ingredients("TOMATO", 0);
    public static final Ingredients ONION = new Ingredients("ONION", 1);
    public static final Ingredients TZATZIKI = new Ingredients("TZATZIKI", 2);
    public static final Ingredients POTATO = new Ingredients("POTATO", 3);
    public static final Ingredients MUSTARD = new Ingredients("MUSTARD", 4);
    public static final Ingredients SOUVLAKI = new Ingredients("SOUVLAKI", 5);
    public static final Ingredients GYROS = new Ingredients("GYROS", 6);

    private final String name;
    private final int ordinal;

    private Ingredients(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
        VALUES[ordinal] = this;  // Add to the static array
    }

    // Getters
    public int ordinal() {
        return ordinal;
    }

    public String getName() {
        return name;
    }

    public static Ingredients[] values() {
        return VALUES.clone();  // Return a copy of the array
    }

    public static Ingredients valueOf(String name) {
        for (Ingredients ingredient : VALUES) {
            if (ingredient.name.equals(name)) {
                return ingredient;
            }
        }
        throw new IllegalArgumentException("No enum constant " + name);
    }

    @Override
    public String toString() {
        return name;
    }
}

Πολυμορφισμός με ταίριαγμα προτύπων

Με εντολές switch μπορούμε να γράψουμε κώδικα για συγκεκριμένους τύπους με βάση το ταίριασμα προτύπων (pattern matching).

class PaternMatch {

    class RetailCustomer {}
    class BusinessCustomer {}

    /** Return the document a given object shall receive */
    private static String documentName(Object o) {
        return switch (o) {
            case RetailCustomer rc -> "receipt";
            case BusinessCustomer bc -> "invoice";
            default -> "unknown document";
        };
    }

    public static void main(String[] args) {
        var retailCustomer = new RetailCustomer();
        var businessCustomer = new BusinessCustomer();
        System.out.println("Retail customer gets "
                + documentName( retailCustomer));
        System.out.println("Business customer gets "
                + documentName(businessCustomer));
    }
}

Εγγραφές

Παράδειγμα


public class RecordDemo {
    record Point(int x, int y) {}

    public static void main(String[] args) {
        var a = new Point(5, 12); // Pythagorean triple
        System.out.println("Point " + a + " has magnitude "
                + Math.sqrt(a.x() * a.x() + a.y() * a.y()));
    }
}

Εγγραφή ως κλάση

Η αντίστοιχη κλάση χωρίς τη χρήση εγγραφής θα είχε την παρακάτω μορφή.

public class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    // Getters
    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    // Object methods
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Point point = (Point) o;
        return x == point.x && y == point.y;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }

    @Override
    public String toString() {
        return "Point{" + "x=" + x + ", y=" + y + '}';
    }
}

Ταίριαγμα προτύπων σε εγγραφές

Σε εγγραφές μπορούμε να ταιριάξουμε και τα ορίσματά τους.

class PaternMatch {

    record Point2D(double x, double y) {}
    record Point3D(double x, double y, double z) {}

    /** Output the magnitude of the specified object */
    private static void printMagnitude(Object o) {
        System.out.println("Magnitude of " + o + " is " +
            switch (o) {
                case Point2D(double x, double y) -> Math.sqrt(x * x + y * y);
                case Point3D(double x, double y, double z) ->
                    Math.sqrt(x * x + y * y + z * z);
                default -> throw new IllegalArgumentException("Unexpected type: "
                        + o.getClass().getName());
            }
        );
    }

    public static void main(String[] args) {
        printMagnitude(new Point2D(3, 4)); // Pythagorean triple
        printMagnitude(new Point3D(1, 4, 8)); // Pythagorean quadruple
    }
}

Το σχεδιαστικό πρότυπο singleton

Παράδειγμα singleton

Άσκηση: δημιουργία μιας κλάσης

Άσκηση 4

Μπορείτε να κατεβάσετε το αντίστοιχο αρχείο και να στείλετε τους βαθμούς σας από τους δεσμούς που βρίσκονται στη σελίδα των ασκήσεων.

Βιβλιογραφία

Περιεχόμενα