Метод (компьютерное программирование) - Method (computer programming)

Метод в объектно-ориентированном программировании (ООП) является процедурой , связанной с сообщением и объектом . Объект состоит из данных и поведения ; они составляют интерфейс , который определяет, как объект может использоваться любым из его различных потребителей.

Данные представлены как свойства объекта, а поведение - как методы. Например, у Windowобъекта могут быть такие методы, как openи close, а его состояние (открыто или закрыто в любой момент времени) будет свойством.

В программировании на основе классов методы определяются внутри класса , а объекты являются экземплярами данного класса. Одной из наиболее важных возможностей, которые предоставляет метод, является переопределение метода - одно и то же имя (например, area) может использоваться для нескольких различных типов классов. Это позволяет отправляющим объектам вызывать поведение и делегировать реализацию этого поведения принимающему объекту. Метод в программировании на Java устанавливает поведение объекта класса. Например, объект может послать areaсообщение другому объекту и соответствующая формула вызывается ли принимающий объект а rectangle, circle, triangleи т.д.

Методы также предоставляют интерфейс, который другие классы используют для доступа и изменения свойств объекта; это известно как инкапсуляция . Инкапсуляция и переопределение - две основные отличительные особенности между методами и вызовами процедур.

Переопределение и перегрузка

Переопределение и перегрузка метода - два наиболее важных отличия метода от обычного вызова процедуры или функции. Переопределение относится к подклассу, переопределяющему реализацию метода своего суперкласса. Например, это findAreaможет быть метод, определенный для класса формы triangle, и т.д., каждый из которых будет определять соответствующую формулу для вычисления своей площади. Идея состоит в том, чтобы рассматривать объекты как «черные ящики», чтобы изменения во внутренней части объекта могли быть сделаны с минимальным воздействием на другие объекты, которые его используют. Это называется инкапсуляцией и призвано упростить поддержку и повторное использование кода.

С другой стороны, перегрузка метода относится к различению кода, используемого для обработки сообщения, на основе параметров метода. Если рассматривать принимающий объект как первый параметр в любом методе, то переопределение - это просто частный случай перегрузки, когда выбор основан только на первом аргументе. Следующий простой пример Java иллюстрирует разницу:

Методы аксессора, мутатора и менеджера

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

Эти методы обеспечивают уровень абстракции, который упрощает инкапсуляцию и модульность . Например, если класс банковского счета предоставляет getBalance()метод доступа для получения текущего баланса (вместо прямого доступа к полям данных баланса), то более поздние версии того же кода могут реализовать более сложный механизм для получения баланса (например, база данных fetch) без изменения зависимого кода. Концепции инкапсуляции и модульности не уникальны для объектно-ориентированного программирования. Действительно, во многих отношениях объектно-ориентированный подход является просто логическим продолжением предыдущих парадигм, таких как абстрактные типы данных и структурированное программирование .

Конструкторы

Конструктор представляет собой метод , который вызывается в начале жизни объекта для создания и инициализации объекта, процесса , называемого строительства (или экземпляра ). Инициализация может включать в себя получение ресурсов. Конструкторы могут иметь параметры, но обычно не возвращают значения на большинстве языков. См. Следующий пример на Java:

public class Main {
    String _name;
    int _roll;

    Main(String name, int roll) { // constructor method
        this._name = name;
        this._roll = roll;
    }
}

Деструкторы

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

Финализаторы

В языках со сборкой мусора , таких как Java , C # и Python , деструкторы известны как финализаторы . У них схожее назначение и функции с деструкторами, но из-за различий между языками, использующими сборку мусора, и языками с ручным управлением памятью, последовательность их вызова различается.

Абстрактные методы

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

Пример

Следующий код Java показывает абстрактный класс, который необходимо расширить:

abstract class Shape {
    abstract int area(int h, int w); // abstract method signature
}

Следующий подкласс расширяет основной класс:

public class Rectangle extends Shape {
    @Override
    int area(int h, int w) {
        return h * w;
    }
}

Реабстракция

Если подкласс обеспечивает реализацию абстрактного метода, другой подкласс может снова сделать его абстрактным. Это называется реабстракцией .

На практике это используется редко.

Пример

В C # виртуальный метод можно переопределить абстрактным методом. (Это также относится к Java, где все не приватные методы являются виртуальными.)

class IA
{
    public virtual void M() { }
}
abstract class IB : IA
{
    public override abstract void M(); // allowed
}

Методы интерфейсов по умолчанию также могут быть реорганизованы, требуя подклассов для их реализации. (Это также относится к Java.)

interface IA
{
    void M() { }
}
interface IB : IA
{
    abstract void IA.M();
}
class C : IB { } // error: class 'C' does not implement 'IA.M'.

Методы класса

Методы класса - это методы, которые вызываются для класса, а не для экземпляра. Обычно они используются как часть метамодели объекта . Т.е. для каждого определенного класса создается экземпляр объекта класса в метамодели. Протоколы метамодели позволяют создавать и удалять классы. В этом смысле они предоставляют те же функции, что и конструкторы и деструкторы, описанные выше. Но в некоторых языках, таких как Common Lisp Object System (CLOS), метамодель позволяет разработчику динамически изменять объектную модель во время выполнения: например, создавать новые классы, переопределять иерархию классов, изменять свойства и т. Д.

Специальные методы

Специальные методы очень зависят от языка, и язык может не поддерживать ни одного, некоторых или всех специальных методов, определенных здесь. Компилятор языка может автоматически генерировать специальные методы по умолчанию, или программисту может быть разрешено опционально определять специальные методы. Большинство специальных методов не могут быть вызваны напрямую, а компилятор генерирует код для их вызова в подходящее время.

Статические методы

Статические методы должны относиться ко всем экземплярам класса, а не к какому-либо конкретному экземпляру. В этом смысле они похожи на статические переменные . Примером может быть статический метод для суммирования значений всех переменных каждого экземпляра класса. Например, если бы был Productкласс, у него мог бы быть статический метод для вычисления средней цены всех продуктов.

В Java обычно используется статический метод:

Math.max(double a, double b)

Этот статический метод не имеет объекта-владельца и не работает в экземпляре. Он получает всю информацию из своих аргументов.

Статический метод можно вызвать, даже если экземпляры класса еще не существуют. Статические методы называются «статическими», потому что они разрешаются во время компиляции на основе класса, для которого они вызываются, а не динамически, как в случае с методами экземпляра, которые разрешаются полиморфно на основе типа среды выполнения объекта.

Операторы присваивания копий

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

Операторские методы

Методы операторов определяют или переопределяют символы операторов и определяют операции, которые должны выполняться с символом и соответствующими параметрами метода. Пример C ++:

#include <string>

class Data {
 public:
  bool operator<(const Data& data) const { return roll_ < data.roll_; }
  bool operator==(const Data& data) const {
    return name_ == data.name_ && roll_ == data.roll_;
  }

 private:
  std::string name_;
  int roll_;
};

Функции-члены в C ++

Некоторые процедурные языки были расширены объектно-ориентированными возможностями для использования большого набора навыков и унаследованного кода для этих языков, но по-прежнему обеспечивают преимущества объектно-ориентированной разработки. Пожалуй, наиболее известным примером является С ++ , объектно-ориентированный расширение С языка программирования. Из-за требований к дизайну для добавления объектно-ориентированной парадигмы к существующему процедурному языку передача сообщений в C ++ имеет некоторые уникальные возможности и терминологию. Например, в C ++ метод известен как функция-член . В C ++ также есть концепция виртуальных функций, которые являются функциями-членами, которые могут быть переопределены в производных классах и допускают динамическую отправку .

Виртуальные функции

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

Пример C ++:

#include <iostream>
#include <memory>

class Super {
 public:
  virtual ~Super() = default;

  virtual void IAm() { std::cout << "I'm the super class!\n"; }
};

class Sub : public Super {
 public:
  void IAm() override { std::cout << "I'm the subclass!\n"; }
};

int main() {
  std::unique_ptr<Super> inst1 = std::make_unique<Super>();
  std::unique_ptr<Super> inst2 = std::make_unique<Sub>();

  inst1->IAm();  // Calls |Super::IAm|.
  inst2->IAm();  // Calls |Sub::IAm|.
}

Смотрите также

Примечания

использованная литература