Опубликован: 27.09.2006 | Уровень: для всех | Доступ: свободно
Лекция 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));
    }
}
Анастасия Халудорова
Анастасия Халудорова
подавляющее большиство фукций на пространстве последовательостей?
екатерина яковлева
екатерина яковлева
как получить сертификат,что для этого нужно?
Дмитрий Карпов
Дмитрий Карпов
Россия, Нижний Новгород
Антон Никитин
Антон Никитин
Россия, Хабаровск