Московский государственный индустриальный университет
Опубликован: 27.09.2006 | Доступ: свободный | Студентов: 3332 / 380 | Оценка: 4.17 / 3.79 | Длительность: 24:17:00
Специальности: Программист
Лекция 10:

Основы объектно-ориентированного программирования

Классы и объекты в языке Java

Для знакомства с базовым для объекно-ориентированного программирования понятием класса, рассмотрим класс R2Point, задающий точку на плоскости.

Пример программы

//Класс, описывающий точку (Point) на плоскости (R2).
class R2Point {
    // Переменные экземпляра, задающие координаты точки.
    private double x, y;

    // Конструктор с параметрами.
    public R2Point(double x, double y) {
        this.x = x; this.y = y;
    }
    // Метод экземпляра - расстояние до начала координат.
    public double dist0() {
        return Math.sqrt(x*x + y*y);
    }
}

Для того, чтобы создать экземпляр этого класса, в программе следует предварительно объявить переменную типа R2Point, а затем воспользоваться оператором new. Объявление переменной можно совмещать с созданием нового объекта, что демонстрируется в следующей программе, находящей расстояние от точки до начала координат.

R2Point p = new R2Point(1.,2.);
double  d = p.dist0();

Этот пример объясняет, почему такой стиль записи называют объектно-ориентированным: при вызове метода в центре внимания находится объект p, а не метод dist0. Этот метод не нуждается в аргументе — объект, над которым производится данное действие, уже указан в данной конструкции. Именно по этой причине внутри метода dist0 можно работать с величинами x и y, принадлежащими конкретному экземпляру объекта. Имена x и y в теле метода dist0 являются сокращениями от this.x и this.y соответственно, где ключевое слово this является указателем на тот экземпляр класса, с которым должен работать метод. Часто нет необходимости явно использовать этот неявный аргумент любого метода экземпляра, однако иногда это необходимо. Примером является конструктор класса R2Point.

Конструктор — это метод, имеющий имя, совпадающее с именем класса. Две основные задачи конструктора заключаются в выделении памяти под вновь создаваемый объект и его инициализация. В рассматриваемом нами примере точки на плоскости совершенно бессмысленно пытаться как-либо работать с объектом (точкой), у которого не заданы координаты. Поэтому конструктор объекта типа R2Point, который вызывается с помощью метода new, должен записать в переменные конкретного экземпляра его координаты. В том случае, если в качестве имен аргументов конструктора выбраны x и y (а это вполне естественный выбор), для обеспечения доступа к переменным экземпляра необходимо использование ключевого слова this. В объявлении конструктора не разрешается указывать возвращаемый тип (хотя неявно всегда возвращается объект this ), а в его теле нельзя использовать оператор return.

Если в некоторой задаче необходимо создавать новые объекты типа R2Point, вводя их координаты с клавиатуры, то может возникнуть желание реализовать это непосредственно в конструкторе.

Пример программы

//Класс, описывающий точку (Point) на плоскости (R2).
class R2Point{
    // Переменные экземпляра, задающие координаты точки.
    private double x, y;

    // Конструктор с параметрами.
    public R2Point(double x, double y) {
        this.x = x; this.y = y;
    }
    // Еще один конструктор, позволяющий вводить
    // координаты вновь создаваемой точки с клавиатуры.
    public R2Point() throws Exception {
        x = Xterm.inputDouble("x -> ");
        y = Xterm.inputDouble("y -> ");
    }
    // Метод класса - расстояние до начала координат.
    public static double dist0(R2Point a) {
        return Math.sqrt(a.x*a.x + a.y*a.y);
    }
    // Метод экземпляра - расстояние до начала координат.
    public double dist0() {
        return Math.sqrt(x*x + y*y);
    }
}

Такой класс выглядит на первый взгляд весьма странно — в нем разные методы имеют одинаковые имена. Компилятор, однако, может различить их. Признак, по которому это происходит — количество и типы аргументов у различных методов. Так, если оператор new для объекта R2Point имеет два аргумента, то вызывается первый из конструкторов, а если аргументов нет — второй.

Вторым интересным моментом в этом примере является иллюстрация использования метода класса. Первый из двух методов dist0 описан с ключевым словом static, что и делает его методом класса. Такой метод не может быть вызван от конкретного объекта с помощью оператора "точка", ему не передается указатель this на экземпляр, а само это ключевое слово не может быть использовано в его теле. Приведенная ниже программа находит расстояние от точки p до начала координат двумя различными эквивалентными методами.

R2Point p = new R2Point(1.,2.);
double  d1 = p.dist0();
double  d2 = R2Point.dist0(p);

Могут существовать и переменные класса — это такие переменные, которые всегда имеются ровно в одном экземпляре, независимо от того как много имеется объектов данного класса. Для их описания также применяется ключевое слово static.

Обычно класс содержит целый ряд методов, как экземпляра, так и класса, набор которых определяется конкретной задачей. Вот как выглядит описание класса R2Point, которое будет использовано в следующем параграфе в реальном проекте.

Пример программы

//Класс, описывающий точку (Point) на плоскости (R2).
class R2Point {
    private double x, y;

    public R2Point(double x, double y) {
        this.x = x; this.y = y;
    }
    public R2Point() throws Exception {
        x = Xterm.inputDouble("x -> ");
        y = Xterm.inputDouble("y -> ");
    }
    public static double dist(R2Point a, R2Point b) {
        return Math.sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    public static double area(R2Point a, R2Point b, R2Point c) {
        return 0.5*((a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x));
    }
    public static boolean equal(R2Point a, R2Point b) {
        return a.x==b.x && a.y==b.y;
    }
    public static boolean isTriangle(R2Point a, R2Point b, R2Point c) {
        return area(a, b, c) != 0.0;
    }
    public boolean inside(R2Point a, R2Point b) {
        return (a.x <= x && x <= b.x || a.x >= x && x >= b.x) &&
            (a.y <= y && y <= b.y || a.y >= y && y >= b.y);
    }
    public boolean light(R2Point a, R2Point b) {
        double s = area(a, b, this);
        return s < 0.0 || ( s == 0.0 && ! inside(a, b));
    }
}
Анастасия Халудорова
Анастасия Халудорова
екатерина яковлева
екатерина яковлева