Перегрузка свойств объектов и вызовов методов


Содержание

Перегрузка методов

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

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

Совершенно недостаточно, чтобы два метода отличались только типами возвращаемых значений. Они должны также отличаться типами или числом своих параметров. (Во всяком случае, типы возвращаемых значений дают недостаточно сведений компилятору C#, чтобы решить, какой именно метод следует использовать.) Разумеется, перегружаемые методы могут отличаться и типами возвращаемых значений. Когда вызывается перегружаемый метод, то выполняется тот его вариант, параметры которого соответствуют (по типу и числу) передаваемым аргументам.

Давайте рассмотрим пример использования перегрузки методов:

Как видите метод ui перегружается три раза. Модификаторы параметров ref и out также учитываются, когда принимается решение о перегрузке метода. Несмотря на то что модификаторы параметров ref и out учитываются, когда принимается решение о перегрузке метода, отличие между ними не столь существенно. Давайте добавим еще одну перегрузку в вышеуказанный пример:

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

Допустим, что требуется функция, определяющая абсолютное значение. В языках, не поддерживающих перегрузку методов, обычно приходится создавать три или более вариантов такой функции с несколько отличающимися, но все же разными именами. Например, в С функция abs() возвращает абсолютное значение целого числа, функция labs() — абсолютное значение длинного целого числа, а функция fabs () — абсолютное значение числа с плавающей точкой обычной (одинарной) точности.

В С перегрузка не поддерживается, и поэтому у каждой функции должно быть свое, особое имя, несмотря на то, что все упомянутые выше функции, по существу, делают одно и то же — определяют абсолютное значение. Но это принципиально усложняет положение, поскольку приходится помнить имена всех трех функций, хотя они реализованы по одному и тому же основному принципу. Подобные затруднения в C# не возникают, поскольку каждому методу, определяющему абсолютное значение, может быть присвоено одно и то же имя. И действительно, в состав библиотеки классов для среды .NET Framework входит метод Abs(), который перегружается в классе System.Math для обработки данных разных числовых типов. Компилятор C# сам определяет, какой именно вариант метода Abs() следует вызывать, исходя из типа передаваемого аргумента.

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

Чтобы закрепить понятие перегрузки методов, давайте рассмотрим перегрузку встроенного метода IndexOf класса String пространства имен System:

В данном примере используется только часть доступных перегрузок метода IndexOf, если бы C# не поддерживал перегрузки, то пришлось бы присваивать каждому методу свое имя, что конечно же очень неудобно. В данном случае метод IndexOf реализует несколько перегрузок, для поиска символов и подстрок в исходной строке.

Перегрузка методов

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

При вызове перегруженного метода для определения нужной версии Java использует тип и/или количество аргументов метода. Следовательно, перегруженные методы должны различаться по типу и/или количеству их параметров. Хотя возвращаемые типы перегруженных методов могут быть различны, самого возвращаемого типа не достаточно для различения двух версий метода. Когда Java встречает вызов перегруженного метода, она просто выполняет ту его версию, параметры которой соответствуют аргументам, использованным в вызове.

Следующий простой пример иллюстрирует перегрузку метода.

// Демонстрация перегрузки методов.
class OverloadDemo <
void test () <
System.out.println(«Параметры отсутствуют»);
// Проверка перегрузки на наличие одного целочисленного параметра.
void test(int а) <
System.out.println(«а: » + a);
>
// Проверка перегрузки на наличие двух целочисленных параметров.
void test(int a, int b) <
System.out .println («а и b: » + a + » » + b) ;
>
// Проверка перегрузки на наличие параметра типа double
double test(double a) <
System.out.println(«double a: » + a);
return a*a;
>
>
class Overload <
public static void main(String args[]) <
OverloadDemo ob = new OverloadDemo() ;
double result;
// вызов всех версий метода test()
ob.test () ;
ob.test (10);
ob.test (10, 20);
result = ob.test(123.25) ;
System.out.println(«Результат ob.test(123.25) : » + result);
>
>

Эта программа генерирует следующий вывод:

Параметры отсутствуют
а: 10
а и b: 10 20
double а: 123.25
Результат ob.test(123.25): 15190.5625

Как видите, метод test () перегружается четыре раза. Первая версия не принимает никаких параметров, вторая принимает один целочисленный параметр, третья — два целочисленных параметра, а четвертая — один параметр типа double. То, что четвертая версия метода test () возвращает также значение, не имеет никакого значения для перегрузки, поскольку возвращаемый тип никак не влияет на разрешение перегрузки.

При вызове перегруженного метода Java ищет соответствие между аргументами, которые были использованы для вызова метода, и параметрами метода. Однако это соответствие не обязательно должно быть полным. В некоторых случаях к разрешению перегрузки может применяться автоматическое преобразование типов Java. Например, рассмотрим следующую программу:

// Применение автоматического преобразования типов к перегрузке.
class OverloadDemo <
void test () <
System.out.println(«Параметры отсутствуют»);
>
// Проверка перегрузки на наличие двух целочисленных параметров.
void test(int a, int b) <
System.out.println(«а и b: » + a + » » + b);
class Overload <
public static void main(String args[]) <
OverloadDemo ob = new OverloadDemo ();
int i = 88;
ob. test () ;
ob.test(10, 20) ;
ob.test(i);
// этот оператор вызовет test(double)
ob.test(123.2);
// этот оператор вызовет test(double)
>
>

Программа генерирует следующий вывод:

Параметры отсутствуют
а и b: 10 20

Внутреннее преобразование test(double) а: 88
Внутреннее преобразование test(double) а: 123.2

Как видите, эта версия класса OverloadDemo не определяет перегрузку test (int). Поэтому при вызове метода test () с целочисленным аргументом внутри класса Overload какой-то соответствующий метод отсутствует. Однако Java может автоматически преобразовывать тип integer в тип double, и это преобразование может использоваться для разрешения вызова. Поэтому после того, как версия test (int) не обнаружена, Java повышает тип i до double, а затем вызывает метод test (double). Конечно, если бы метод test (int) был определен, вызвался бы он. Java будет использовать автоматическое преобразование типов только при отсутствии полного соответствия.

Перегрузка методов поддерживает полиморфизм, поскольку это один из способов реализации в Java концепции «один интерфейс, несколько методов». Для пояснения приведем следующие рассуждения. В тех языках, которые не поддерживают перегрузку методов, каждому методу должно быть присвоено уникальное имя. Однако часто желательно реализовать, по сути, один и тот же метод для различных типов данных. Например, рассмотрим функцию вычисления абсолютного значения. Обычно в языках, которые не поддерживают перегрузку, существует три или более версии этой функции со слегка различающимися именами. Например, в С функция abs () возвращает абсолютное значение значения типа integer, labs () — значения типа long integer, a fabs () — значения с плавающей точкой. Поскольку язык С не поддерживает перегрузку, каждая функция должна обладать собственным именем, несмотря на то, что все три функции выполняют по существу одно и то же действие. В результате в концептуальном смысле ситуация становится более сложной, чем она есть на самом деле. Хотя каждая из функций построена на основе одной и той же концепции, программист вынужден помнить три имени. В Java подобная ситуация не возникает, поскольку все методы вычисления абсолютного значения могут использовать одно и то же имя. И действительно, стандартная библиотека классов Java содержит метод вычисления абсолютного значения, названный abs (). Перегрузки этого метода для обработки всех численных типов определены в Java-классе Math. Java выбирает для вызова нужную версию метода abs () в зависимости от типа аргумента.

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

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

Перегрузка методов и аксессоры в PHP

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

Все методы перегрузки объявляются исключительно только как «public».

Пример перегрузки метода:

Результатом работы будет вывод фразы «Вызван метод «method_base» производного класса».

Таким образом, метод base_class::method_base() не вызывается при обращении к объекту производного класса «derivative_class».

Однако в рамках производного класса остаётся возможность вызвать метод базового класса, обратившись к нему при помощи префикса «parent::».

Ниже будет представлен пример перегрузки метода «method_base()», при котором метод производного класса сначала вызывает метод базового класса.

Результат покажет уже две строчки «Вызван метод «method_base» базового класса» и «Вызван метод «method_base» производного класса».

Таким образом, при помощи перегрузки метода можно как расширить метод базового класса, так и полностью заменить его уже новым методом.

Ниже будет продемонстрирован пример перегрузки методов с класса «mysqli»:

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

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

Помимо этого в PHP существует ещё два «магических» метода (аксессоры),при помощи которых можно перегрузить свойства, которые вызываются при обращении к свойству класса и при изменении его значения, — это методы «__get()» и «__set()».

Илон Маск рекомендует:  Cnstats как решение проблем со статистикой сайта

Данные методы «__get()» и «__set()» позволяют легко проводить динамическое назначение свойств объектам, а в качестве параметров этим методам передаются имена свойств.

А также, метод «__set()» может получить и значение, которое присваивается указанному свойству. Приведём пример:

Как видно из примера, класс «setget» перехватывает обращения к членам и создает соответствующий элемент в массиве $_array.

При попытке присвоить члену значение, создаётся новый элемент в массиве $_array.

Если член в классе уже существует, то аксессоры «__set()» и «__get()» перехватывают обращение к нему, если он имеет спецификатор доступа «private» и не перехватывают, если он имеет спецификатор «public».

Ещё существуют новый метод перегрузки «__callStatic()» который добавлен в PHP 5.3, и метод «__call». Пример:

$_Home содержит имя метода, а $_arg массив в котором храняться параметры которые передаются из метода $_Home.

Комментировать


Однако перегружать методы можно только в процессе наследования. В одном и том же классе нельзя записать методы с одинаковыми названиями, но с разными аргументами, так как сигнатура метода не зависит от аргументов. Поддержка полиморфизма в PHP неполная.

Я извиняюсь, что придираюсь к терминологии, но полагаю, что в статье подразумевается переопределение (override), а не перегрузка (overload). Последнее подразумевает выбор одного из методов с одним и тем же названием, в зависимости от сигнатуры метода, а первое — реализацию в классе метода с такой же сигнатурой, как и в классе родителя, и выбор во время выполнения программы нужной реализации, в зависимости от конкретного типа объекта.

Java перегрузка метода, где в качестве параметра объект одного из классов-наследников

Есть абстрактный класс MyClass от которого наследуются MyClassA И MyClassB.
Есть фабрика, которая в зависимости от принимаемых параметров метода create возвращает объект класса MyClassA или MyClassB.
И есть перегруженный для MyClassA и MyClassB метод Foo().

Но в итоге компилятор говорит, что метод Foo не применим для аргументов класса MyClass. Что я сделал не так?

2 ответа 2

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

чтобы исправить ошибку в этой строке надо переписать

У вас методы Foo() принимают аргументы либо MyClassA , либо MyClassB , а вы подаете на вход объект типа MyClass . Я думаю ваш в вопрос в том, почему это не работает, ведь это предок этих классов?
Дело в том, что наследники расширяют функционал родителя. То есть в наследнике есть всё, что есть в родителе плюс еще что-то дополнительно (методы, свойства). Рассмотрим на примере животных:
Есть базовый класс — Animal . Animal умеет eat() и sleep() . И есть наследники — Cat и Bird . Помимо того, что эти наследники умеют так же eat() и sleep() , они обладают дополнительными способностями, у кота это haunt() , у птицы fly() .
И теперь смотрите, в чем суть. У вас метод Foo() принимает на вход либо Cat , либо Bird . Внутри этих методов мы можете использовать функционал методы наследников ( haunt() в случае с Cat и fly() в случае с Bird ), но в коде вы передаете Animal , а Animal не умеет ни fly() , ни haunt() .
Вот чтобы такого не дай бог не произошло, компилятор не дает вам использовать предка в тех местах, где ожидаются наследники.

Методы Java — как вызывать и использовать

В объектно-ориентированном программировании метод — это именованный блок кода, который объявляется внутри класса и может быть использован многократно. Если вы знакомы с процедурным программированием (Pascal, Basic), вспомните, что такое функция — по принципу работы у неё и метода много общего.

Хорошо написанный метод решает одну практическую задачу: находит квадратный корень из числа (как штатный метод sqrt() в Java), преобразует число в строку (метод toString()), присваивает значения полям объекта и так далее.

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

Штатные — встроенные — методы языка работают со служебными объектами. Например, метод print в Java выводит значения в консоль. Вызывают его так:

Обратите внимание на структуру: у класса System есть поле out — поток ввода/вывода. Поле — тоже объект, и у него есть метод print(), который мы вызываем.

Ещё есть метод println(), который при выводе значений автоматически переводит каретку на следующую строку. Это избавляет от необходимости ставить «\n» в месте переноса строки.

Чтобы Java-приложение могло работать, в его базовом классе обязательно нужно объявить метод main.

Как видите, в качестве параметра main принимает массив строк, в данном случае — параметров запуска.

Объявление и определение метода в Java

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

В примере ниже метод должен найти большее из двух целых чисел, поэтому тип возвращаемого значения — int:

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

В теле метода заводим переменную max, куда потом запишем большее число. Далее сравниваем значения, фиксируем большее в max и возвращаем.

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

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

Как вызвать метод в Java

Метод с модификатором public можно вызывать из любого класса, в том числе размещенного во внешнем файле. Если нужно, чтобы метод был доступен исключительно внутри своего класса, применяют модификатор private. Есть и более мягкий вариант ограничения доступа: методы с модификатором protected доступны подклассам своего класса и другим классам из того же пакета. Чем сложнее получить доступ к методу извне, тем безопаснее — ниже риск ошибок.

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

Для простоты мы сделали методы публичными и статическими и разместили их в главном классе программы.

Вызывают методы двумя способами — в зависимости от того, возвращают они что-то или нет. Если да, подставляем значение, куда нам нужно:

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

После вызова метод управляет программой до окончания своей работы: пока в его теле не сработает оператор возврата или прерывания, либо пока не будут выполнены все находящиеся в нём инструкции.

Вызовем theWarning, который ничего не возвращает:

Этот метод обходится без помощников — делает, что должен, и передаёт управление последующему коду.

Вызов метода из другого класса

А если бы maxFinder находился в отдельном классе и был не статическим? Тогда для его вызова пришлось бы сначала создать объект класса, в котором он находится. Допустим, метод находится в классе SampleClass. Вызываем:

Статический метод вызывают через точку от имени класса — вот так:

Перегрузка методов в Java

Что, если нам нужно сравнивать не только целые числа, но и числа с плавающей точкой? Реализовать это поможет перегрузка метода. Копипастим метод maxFinder в тот же класс, заменяем типы всех задействованных значений на double:

Имя метода не меняем! Это и есть перегрузка: компилятор сам выберет, какую из версий метода использовать — в зависимости от того, значения какого типа сравниваем.

Ключевое слово this в методах Java

Ключевое слово this позволяет ссылаться на экземпляры класса: их переменные, методы и конструкторы. Используют this только внутри метода или конструктора экземпляра. Например, вот так можно связать входные параметры метода с одноименными параметрами конкретного экземпляра класса:

Ещё пример — вызов одного конструктора из другого:

Это называется «явный вызов конструктора».

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

Абстрактным называют метод, который объявлен без реализации — он не имеет ни тела, ни даже фигурных скобок. Перед именем такого метода ставят модификатор abstract:

Зачем он такой нужен? В качестве шаблона для других методов из других классов. Вот есть у нас абстрактный класс «Строение», а в нём — абстрактный метод «возвести». Реализовывать эти абстракции нужно через несколько неабстрактных классов-наследников и их методы. Пример: класс «Хижина» — метод «стройХижину», класс «Мост» — метод «стройМост» и др.

Поскольку конкретной реализации у абстрактного класса нет, экземпляры его создавать нельзя. Он — шаблон, который задаёт структуру для других классов и содержит объявления методов.

Кроме этого, рекомендуем помотреть вебинар по введению в ООП на Java, где также будет рассматриваться работа с методами и конструкторами.

В объектно-ориентированном программировании метод — это именованный блок кода, который объявляется внутри класса и может быть использован многократно. Если вы знакомы с процедурным программированием (Pascal, Basic), вспомните, что такое функция — по принципу работы у неё и метода много общего.


Хорошо написанный метод решает одну практическую задачу: находит квадратный корень из числа (как штатный метод sqrt() в Java), преобразует число в строку (метод toString()), присваивает значения полям объекта и так далее.

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

Штатные — встроенные — методы языка работают со служебными объектами. Например, метод print в Java выводит значения в консоль. Вызывают его так:

Обратите внимание на структуру: у класса System есть поле out — поток ввода/вывода. Поле — тоже объект, и у него есть метод print(), который мы вызываем.

Ещё есть метод println(), который при выводе значений автоматически переводит каретку на следующую строку. Это избавляет от необходимости ставить «\n» в месте переноса строки.

Чтобы Java-приложение могло работать, в его базовом классе обязательно нужно объявить метод main.

Как видите, в качестве параметра main принимает массив строк, в данном случае — параметров запуска.

Объявление и определение метода в Java

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

В примере ниже метод должен найти большее из двух целых чисел, поэтому тип возвращаемого значения — int:

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

В теле метода заводим переменную max, куда потом запишем большее число. Далее сравниваем значения, фиксируем большее в max и возвращаем.

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

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

Как вызвать метод в Java

Метод с модификатором public можно вызывать из любого класса, в том числе размещенного во внешнем файле. Если нужно, чтобы метод был доступен исключительно внутри своего класса, применяют модификатор private. Есть и более мягкий вариант ограничения доступа: методы с модификатором protected доступны подклассам своего класса и другим классам из того же пакета. Чем сложнее получить доступ к методу извне, тем безопаснее — ниже риск ошибок.

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

Для простоты мы сделали методы публичными и статическими и разместили их в главном классе программы.

Вызывают методы двумя способами — в зависимости от того, возвращают они что-то или нет. Если да, подставляем значение, куда нам нужно:

Илон Маск рекомендует:  Модульная сетка

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

После вызова метод управляет программой до окончания своей работы: пока в его теле не сработает оператор возврата или прерывания, либо пока не будут выполнены все находящиеся в нём инструкции.

Вызовем theWarning, который ничего не возвращает:

Этот метод обходится без помощников — делает, что должен, и передаёт управление последующему коду.

Вызов метода из другого класса

А если бы maxFinder находился в отдельном классе и был не статическим? Тогда для его вызова пришлось бы сначала создать объект класса, в котором он находится. Допустим, метод находится в классе SampleClass. Вызываем:

Статический метод вызывают через точку от имени класса — вот так:

Перегрузка методов в Java

Что, если нам нужно сравнивать не только целые числа, но и числа с плавающей точкой? Реализовать это поможет перегрузка метода. Копипастим метод maxFinder в тот же класс, заменяем типы всех задействованных значений на double:

Имя метода не меняем! Это и есть перегрузка: компилятор сам выберет, какую из версий метода использовать — в зависимости от того, значения какого типа сравниваем.

Ключевое слово this в методах Java

Ключевое слово this позволяет ссылаться на экземпляры класса: их переменные, методы и конструкторы. Используют this только внутри метода или конструктора экземпляра. Например, вот так можно связать входные параметры метода с одноименными параметрами конкретного экземпляра класса:

Ещё пример — вызов одного конструктора из другого:

Это называется «явный вызов конструктора».

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

Абстрактным называют метод, который объявлен без реализации — он не имеет ни тела, ни даже фигурных скобок. Перед именем такого метода ставят модификатор abstract:

Зачем он такой нужен? В качестве шаблона для других методов из других классов. Вот есть у нас абстрактный класс «Строение», а в нём — абстрактный метод «возвести». Реализовывать эти абстракции нужно через несколько неабстрактных классов-наследников и их методы. Пример: класс «Хижина» — метод «стройХижину», класс «Мост» — метод «стройМост» и др.

Поскольку конкретной реализации у абстрактного класса нет, экземпляры его создавать нельзя. Он — шаблон, который задаёт структуру для других классов и содержит объявления методов.

Кроме этого, рекомендуем помотреть вебинар по введению в ООП на Java, где также будет рассматриваться работа с методами и конструкторами.

Урок №134. Перегрузка операторов через методы класса

Обновл. 18 Июн 2020 |

Перегрузка операторов через методы класса очень похожа на перегрузку операторов через дружественные функции. Но, при перегрузке оператора через метод класса, левым операндом становится неявный объект, на который указывает скрытый указатель *this.

Перегрузка операторов через методы классов

Вспомним как выглядит перегрузка оператора через дружественную функцию:

Конвертация перегрузки через дружественную функцию в перегрузку через метод класса довольно-таки проста:

Перегружаемый оператор определяется как метод класса, вместо дружественной функции ( Dollars::operator+ вместо friend operator+ ).

Левый параметр из функции перегрузки выбрасывается, вместо него — неявный объект, на который указывает *this.

Внутри тела функции перегрузки все ссылки на левый параметр могут быть удалены (например, dollars.m_dollars становится m_dollars , который неявно ссылается на текущий объект с помощью указателя *this).

Теперь та же перегрузка оператора +, но уже через метод класса:

Обратите внимание, использование оператора + не изменяется (в обоих случаях, dollars1 + 3 ), но реализация отличается. Наша дружественная функция с двумя параметрами становится методом класса с одним параметром, причём левый параметр в перегрузке через дружественную функцию ( &dollars ) в перегрузке через метод класса становится неявным объектом, на который указывает указатель *this.

Рассмотрим детальнее, как обрабатывается выражение dollars1 + 3 .


В перегрузке через дружественную функцию выражение dollars1 + 3 приводит к вызову функции operator+(dollars1, 3) . Здесь есть два параметра.

В перегрузке через метод класса выражение dollars1 + 3 приводит к вызову dollars1.operator+(3) . Обратите внимание, здесь уже один явный параметр, а dollars1 используется как префикс к operator+ . Этот префикс компилятор неявно конвертирует в скрытый левый параметр, на который указывает указатель *this. Таким образом, dollars1.operator+(3) становится вызовом operator+(&dollars1, 3) , что почти идентично перегрузке через дружественную функцию.

Итак, если мы можем перегрузить оператор через дружественную функцию или через метод класса, то что тогда выбрать? Прежде чем мы дадим ответ на этот вопрос, вам нужно узнать ещё несколько деталей.

Не всё может быть перегружено через дружественные функции

Операторы присваивания (=), индекса ([]), вызова функции (()) и выбора члена (->) перегружаются через методы класса — это требование языка C++.

Не всё может быть перегружено через методы класса

В уроке о перегрузке операторов ввода и вывода мы перегружали оператор вывода #include

Однако, через метод класса перегрузить оператор operator+(Dollars, int) через метод класса (как мы делали выше), мы не можем перегрузить operator+(int, Dollars) через метод класса, поскольку int теперь является левым операндом, на который указатель *this указывать не может.

Перегрузка операторов через методы класса не используется, если левый операнд не является классом (например, int), или это класс, который мы не можем изменить (например, std::ostream).

Какой способ перегрузки и когда следует использовать?

В большинстве случаев язык C++ позволяет выбирать самостоятельно способ перегрузки операторов.

Но, при работе с бинарными операторами, которые не изменяют левый операнд (например, operator+), обычно используется перегрузка через обычную или дружественную функции, поскольку такая перегрузка работает для всех типов данных параметров (даже если левый операнд не является объектом класса или является объектом класса, который изменить нельзя). Перегрузка через обычную/дружественную функцию имеет дополнительное преимущество «симметрии», так как все операнды становятся явными параметрами (а не как у перегрузки через метод класса, когда левый операнд становится неявным объектом, на который указывает *this).

При работе с бинарными операторами, которые изменяют левый операнд (например, operator+=), обычно используется перегрузка через методы класса. В этих случаях левым операндом всегда является объект класса, на который указывает скрытый указатель *this.

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

Поэтому:

Для операторов присваивания (=), индекса ([]), вызова функции (()) или выбора члена (->) используйте перегрузку через методы класса.

Для унарных операторов используйте перегрузку через методы класса.

Для перегрузки бинарных операторов, которые изменяют левый операнд (например, operator+=) используйте перегрузку через методы класса, если это возможно.

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

Перегрузка

Перегрузка в PHP означает возможность динамически » создавать » свойства и методы. Эти динамические сущности обрабатываются с помощью «волшебных» методов, которые можно создать в классе для различных видов действий.

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

Все методы перегрузки должны быть объявлены как public.

Ни один аргумент не может быть передан по ссылке в эти «волшебные» методы.

Интерпретация » перегрузки » в PHP отличается от остальных объектно-ориентированных языков. Традиционно перегрузка означает возможность иметь множество одноименных методов с разным количеством или различными типами аргументов.

Список изменений

Версия Описание
5.3.0 Добавлен метод __callStatic(). Добавлено предупреждение об усилении публичной видимости и не-статичном объявлении.
5.1.0 Добавлены методы __isset() и __unset(). Добавлена поддержка для перегрузки приватных свойств с помощью __get().
5.0.0 Добавлен метод __get().

Перегрузка свойств

Метод __set() будет выполнен при записи данных в недоступные свойства.

Метод __get() будет выполнен при чтении данных из недоступных свойств.

Метод __isset() будет выполнен при использовании isset() или empty() на недоступных свойствах.

Метод __unset() будет выполнен при вызове unset() на недоступном свойстве.

Аргумент $name представляет собой имя вызываемого свойства. Метод __set() содержит аргумент $value , представляющий собой значение, которое будет записано в свойство с именем $name .

Перегрузка свойств работает только в контексте объекта. Данные магические методы не будут вызваны в статическом контексте. Поэтому данные методы не должны объявляться статичными. Начиная с версии PHP 5.3.0, при объявлении «волшебного» метода в качестве static будет показано предупреждение.

Возвращаемое значение метода __set() будет проигнорировано из-за способа обработки в PHP оператора присваивания. Аналогично, __get() никогда не вызовется при цепных присваиваниях, например, таких:

Пример #1 Перегрузка свойств с помощью методов __get(), __set(), __isset() и __unset()

class PropertyTest
<
/** Место хранения перегружаемых данных. */
private $data = array();

/** Перегрузка не применяется к объявленным свойствам. */
public $declared = 1 ;

/** Здесь перегрузка будет использована только при доступе вне класса. */
private $hidden = 2 ;

public function __set ( $name , $value )
<
echo «Установка ‘ $name ‘ в ‘ $value ‘\n» ;
$this -> data [ $name ] = $value ;
>

public function __get ( $name )
<
echo «Получение ‘ $name ‘\n» ;
if ( array_key_exists ( $name , $this -> data )) <
return $this -> data [ $name ];
>

$trace = debug_backtrace ();
trigger_error (
‘Неопределенное свойство в __get(): ‘ . $name .
‘ в файле ‘ . $trace [ 0 ][ ‘file’ ] .
‘ на строке ‘ . $trace [ 0 ][ ‘line’ ],
E_USER_NOTICE );
return null ;
>

/** Начиная с версии PHP 5.1.0 */
public function __isset ( $name )
<
echo «Установлено ли ‘ $name ‘?\n» ;
return isset( $this -> data [ $name ]);
>

/** Начиная с версии PHP 5.1.0 */
public function __unset ( $name )
<
echo «Уничтожение ‘ $name ‘\n» ;
unset( $this -> data [ $name ]);
>

/** Не «волшебный» метод, просто для примера. */
public function getHidden ()
<
return $this -> hidden ;
>
>

Перегрузка методов

В контексте объекта при вызове недоступных методов вызывается метод __call().

В статическом контексте при вызове недоступных методов вызывается метод __callStatic().

Аргумент $name представляет собой имя вызываемого метода. Аргумент $arguments представляет собой числовой массив, содержащий параметры, переданные в вызываемый метод $name .

Пример #2 Перегрузка методов с помощью методов __call() и __callStatic()


class MethodTest <
public function __call ( $name , $arguments ) <
// Замечание: значение $name регистрозависимо.
echo «Вызов метода ‘ $name ‘ »
. implode ( ‘, ‘ , $arguments ). «\n» ;
>

/** Начиная с версии PHP 5.3.0 */
public static function __callStatic ( $name , $arguments ) <
// Замечание: значение $name регистрозависимо.
echo «Вызов статического метода ‘ $name ‘ »
. implode ( ‘, ‘ , $arguments ). «\n» ;
>
>

$obj = new MethodTest ;
$obj -> runTest ( ‘в контексте объекта’ );

MethodTest :: runTest ( ‘в статическом контексте’ ); // Начиная с версии PHP 5.3.0
?>

Управляющие операторы и методы

Работа с входным потоком. Предварительная информация

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

Следующий пример демонстрирует способы преобразования поступающей через входной поток (ввод с клавиатуры) информации с целью получения значений арифметического типа:

Перегрузка методов

Имя метода и список типов параметров метода являются его важной характеристикой и называются СИГНАТУРОЙ метода. В C# методы, объявляемые в классе, идентифицируются по сигнатуре. Эта особенность языка позволяет объявлять в классе множество одноименных методов. Такие методы называются перегруженными, а деятельность по их объявлению – перегрузкой.

При написании программного кода, содержащего ВЫРАЖЕНИЯ ВЫЗОВА переопределенных методов, корректное соотнесение выражения вызова метода определяет метод, которому будет передано управление:

Информация о типе возвращаемого значения при этом не учитывается, поскольку в выражении вызова возвращаемое значение метода может не использоваться вовсе.

Способы передачи параметров при вызове метода

Известно два способа передачи параметров при вызове метода:

  • по значению (в силу специфики механизма передачи параметров – только входные),
  • по ссылке (входные и/или выходные).

Передача по значению – БЕЗ спецификаторов (для типов-значений этот способ предполагается по умолчанию). Параметр представляет собой локальную копию значения в методе. В теле метода это означенная переменная , которую можно использовать в методе наряду с переменными, непосредственно объявленными в этом методе. При этом изменение значения параметра НЕ влияет на значение параметра в выражении вызова.

Для организации передачи по ссылке параметра типа значения требуется явная спецификация ref . Для ссылочных типов передача параметра по ссылке предполагается по умолчанию. Спецификатор ref в этом случае не требуется, поскольку другого способа передачи параметра для ссылочных типов просто нет.

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

Выражение вызова метода приобретает свое значение непосредственно по возвращении из вызываемого метода. Этим значением можно воспользоваться только в точке возврата.

Переданные методу «для означивания» параметры со спецификатором out сохраняют свои значения за точкой возврата.

Спецификация способа передачи параметра является основанием для перегрузки метода.

Ссылка и ссылка на ссылку как параметры

На самом деле ВСЕ параметры ВСЕГДА передаются по значению. Это означает, что в области активации создается копия ЗНАЧЕНИЯ параметра. При этом важно, ЧТО копируется в эту область. Для ссылочных типов возможны два варианта:

  • можно копировать адрес объекта (ссылка как параметр),
  • можно копировать адрес переменной, которая указывает на объект (ссылка на ссылку как параметр).

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

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

Следующий программный код демонстрирует специфику передачи параметров:

В результате выполнения программы в окошко консольного приложения выводится информация следующего содержания:

BestProg

Перегрузка методов в классах. Примеры. Преимущество перегрузки методов. Перегрузка конструкторов

Содержание

1. В чем состоит суть перегрузки метода в классе?

Язык программирования C# позволяет осуществлять перегрузку методов в классе. Перегрузка означает использование одного имени для разных методов. Фактически, перегружается имя метода.

Перегрузка метода – это программная реализация нескольких методов для которых выполняются следующие условия:

  • все перегруженные методы носят одинаковое имя;
  • перегруженные методы отличаются параметрами. Точнее говоря, тип параметров или количество параметров в перегруженных методах должны отличаться.

Перегрузка метода в классе – это объявления другого метода с таким самым именем в классе но с отличаемыми параметрами. Параметры перегруженного метода должны отличаться типами или количеством.

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

2. Что такое сигнатура метода? Какие требования к сигнатуре метода с точки зрения перегрузки?

Сигнатура метода – это имя метода и список его параметров. С точки зрения перегрузки к сигнатуре метода относится следующее требование:

  • в одном классе не должно существовать двух методов с одинаковой сигнатурой.


3. Считаются ли перегруженными два метода, которые имеют одинаковые параметры но возвращают разные значения?

Нет. Это ошибка. Согласно синтаксису C# перегруженные методы обязательно должны отличаться параметрами.

4. Примеры перегруженных методов

Пример 1. В классе MaxMethods объявляется перегруженный метод Max() , имеющий 3 реализации. Метод реализует поиск максимума между разным количеством параметров типа int .

Ниже приведено использование перегруженного метода Max() класса MaxMethods

Пример 2. В классе AverageMethods объявляется метод Average(), получающий массив чисел и определяющий среднее арифметическое массива. Метод имеет 2 перегруженные реализации для типов int и float . Количество параметров в перегруженных методах Average() есть одинаковым, однако, типы параметров отличаются.

Ниже продемонстрировано использование перегруженного метода Average()

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

5. Какие особенности перегрузки методов, которые получают параметры с модификаторами ref и out ?

Если попробовать объявить разные реализации метода, который содержит одинаковые параметры отличающиеся между собой только модификаторами ref и out , то компилятор выдаст ошибку.

Например. Пусть нужно реализовать два метода GetPi() , которые возвращают число p типа double. При нижеследующем объявлении этих методов в некотором классе

и попытке компиляции, компилятор выдаст сообщение об ошибке

Это означает, что модификаторы ref и out не изменяют общую сигнатуру метода.

6. Какие преимущества дает перегрузка методов?

Перегрузка методов дает следующие преимущества:

  • нет потребности в объявлении дополнительных методов с разными (отличными) именами для выполнения похожей работы. Тем самым упрощается и уменьшается код программы, что в свою очередь ведет к повышению читабельности программы;
  • реализуется основной принцип полиморфизма – один интерфейс, много методов. Это есть удобным, когда идет обращение по одному имени к методу, а компилятор в зависимости от параметров сам выбирает какую реализацию метода выполнить;
  • обеспечивается удобный доступ к связанным вместе методам на основе общего имени;
  • перегруженные методы могут выполнять абсолютно разную работу, то есть иметь абсолютно разный программный код. Все это зависит от получаемых параметров. Однако, желательно (рекомендуется), чтобы перегруженные методы выполняли одинаковую работу.

7. Перегрузка конструкторов в классе. Примеры

Конструкторы классов могут перегружаться точно также как и методы.

Пример 1. Задан класс CPoint , который реализует точку на координатной плоскости. В классе объявляется два перегруженных конструктора.

Ниже продемонстрировано использование перегруженных конструкторов класса

Пример 2. Задан класс Circle , реализующий окружность на координатной плоскости заданного радиуса. В классе реализованы 4 конструктора, которые получают разное количество параметров. Программный код класса следующий

Ниже продемонстрировано использование перегруженных конструкторов класса

8. Каким образом осуществляется вызов перегруженного конструктора с использованием ключевого слова this ? Общая форма

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

  • constructor_name – имя конструктора, который осуществляет вызов перегруженного конструктора;
  • parameters1 – параметры конструктора, который осуществляет вызов перегруженного конструктора. Этот конструктор вызывается вторым после вызова конструктора, обозначенного ключевым словом this ;
  • parameters2 – параметры перегруженного конструктора, который обозначен ключевым словом this . Этот конструктор вызывается первым.

9. Пример вызова перегруженного конструктора с использованием ключевого слова this

Пример. Реализация класса CPixel , который описывает пиксел на экране монитора. Пиксел характеризуется следующими параметрами:

  • целочисленные координаты x , y ;
  • цвет ( color ).

Класс содержит 2 перегруженных конструктора. В классе продемонстрирован вызов перегруженного конструктора.

Вызов перегруженного конструктора осуществляется с помощью кода

Конструктор с 3 параметрами вызывает конструктор с 1 параметром. При таком вызове параметр, который есть в вызывающем конструкторе, должен быть обязательно в вызываемом конструкторе (конструкторе this ). В нашем случае, обязательным есть параметр _color .

Перегрузка методов

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

При вызове перегруженного метода для определения нужной версии Java использует тип и/или количество аргументов метода. Следовательно, перегруженные методы должны различаться по типу и/или количеству их параметров. Хотя возвращаемые типы перегруженных методов могут быть различны, самого возвращаемого типа не достаточно для различения двух версий метода. Когда Java встречает вызов перегруженного метода, она просто выполняет ту его версию, параметры которой соответствуют аргументам, использованным в вызове.

Следующий простой пример иллюстрирует перегрузку метода.

// Демонстрация перегрузки методов.
class OverloadDemo <
void test () <
System.out.println(«Параметры отсутствуют»);
// Проверка перегрузки на наличие одного целочисленного параметра.
void test(int а) <
System.out.println(«а: » + a);
>
// Проверка перегрузки на наличие двух целочисленных параметров.
void test(int a, int b) <
System.out .println («а и b: » + a + » » + b) ;
>
// Проверка перегрузки на наличие параметра типа double
double test(double a) <
System.out.println(«double a: » + a);
return a*a;
>
>
class Overload <
public static void main(String args[]) <
OverloadDemo ob = new OverloadDemo() ;
double result;
// вызов всех версий метода test()
ob.test () ;
ob.test (10);
ob.test (10, 20);
result = ob.test(123.25) ;
System.out.println(«Результат ob.test(123.25) : » + result);
>
>

Эта программа генерирует следующий вывод:

Параметры отсутствуют
а: 10
а и b: 10 20
double а: 123.25
Результат ob.test(123.25): 15190.5625

Как видите, метод test () перегружается четыре раза. Первая версия не принимает никаких параметров, вторая принимает один целочисленный параметр, третья — два целочисленных параметра, а четвертая — один параметр типа double. То, что четвертая версия метода test () возвращает также значение, не имеет никакого значения для перегрузки, поскольку возвращаемый тип никак не влияет на разрешение перегрузки.

При вызове перегруженного метода Java ищет соответствие между аргументами, которые были использованы для вызова метода, и параметрами метода. Однако это соответствие не обязательно должно быть полным. В некоторых случаях к разрешению перегрузки может применяться автоматическое преобразование типов Java. Например, рассмотрим следующую программу:

// Применение автоматического преобразования типов к перегрузке.
class OverloadDemo <
void test () <
System.out.println(«Параметры отсутствуют»);
>
// Проверка перегрузки на наличие двух целочисленных параметров.
void test(int a, int b) <
System.out.println(«а и b: » + a + » » + b);
class Overload <
public static void main(String args[]) <
OverloadDemo ob = new OverloadDemo ();
int i = 88;
ob. test () ;
ob.test(10, 20) ;
ob.test(i);
// этот оператор вызовет test(double)
ob.test(123.2);
// этот оператор вызовет test(double)
>
>

Программа генерирует следующий вывод:

Параметры отсутствуют
а и b: 10 20

Внутреннее преобразование test(double) а: 88
Внутреннее преобразование test(double) а: 123.2

Как видите, эта версия класса OverloadDemo не определяет перегрузку test (int). Поэтому при вызове метода test () с целочисленным аргументом внутри класса Overload какой-то соответствующий метод отсутствует. Однако Java может автоматически преобразовывать тип integer в тип double, и это преобразование может использоваться для разрешения вызова. Поэтому после того, как версия test (int) не обнаружена, Java повышает тип i до double, а затем вызывает метод test (double). Конечно, если бы метод test (int) был определен, вызвался бы он. Java будет использовать автоматическое преобразование типов только при отсутствии полного соответствия.

Перегрузка методов поддерживает полиморфизм, поскольку это один из способов реализации в Java концепции «один интерфейс, несколько методов». Для пояснения приведем следующие рассуждения. В тех языках, которые не поддерживают перегрузку методов, каждому методу должно быть присвоено уникальное имя. Однако часто желательно реализовать, по сути, один и тот же метод для различных типов данных. Например, рассмотрим функцию вычисления абсолютного значения. Обычно в языках, которые не поддерживают перегрузку, существует три или более версии этой функции со слегка различающимися именами. Например, в С функция abs () возвращает абсолютное значение значения типа integer, labs () — значения типа long integer, a fabs () — значения с плавающей точкой. Поскольку язык С не поддерживает перегрузку, каждая функция должна обладать собственным именем, несмотря на то, что все три функции выполняют по существу одно и то же действие. В результате в концептуальном смысле ситуация становится более сложной, чем она есть на самом деле. Хотя каждая из функций построена на основе одной и той же концепции, программист вынужден помнить три имени. В Java подобная ситуация не возникает, поскольку все методы вычисления абсолютного значения могут использовать одно и то же имя. И действительно, стандартная библиотека классов Java содержит метод вычисления абсолютного значения, названный abs (). Перегрузки этого метода для обработки всех численных типов определены в Java-классе Math. Java выбирает для вызова нужную версию метода abs () в зависимости от типа аргумента.

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

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

Илон Маск рекомендует:  ob_start - включает буферизацию вывода
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL