На самом деле это хороший вопрос, и я видел здесь несколько хороших ответов. На самом деле мне действительно пришлось немного подумать об этом.
Я бы хотел добавить кое-что, чего я не видел ни в одном из других ответов здесь, даже если я не получил ни одного голоса, чтобы будущие читатели могли получить пользу.
Давайте возьмем ваши примеры. (Я отредактировал их так, чтобы они были функционально идентичны - они немного изменились по сравнению с тем, что было выше.)
Версия класса:
<?php
class Image {
private $resource;
function resize($width, $height) {
$resized = imagecreatetruecolor($width, $height);
imagecopyresampled($resized, $this->resource, 0, 0, 0, 0, $width, $height, imagesx($this->resource), imagesy($this->resource));
$this->resource = $resized;
}
}
$image = new Image();
$image->resource = "./someimage.jpg";
$image->resize(320, 240);
И версия функции:
function resize($width, $height, $resource) {
$resized = imagecreatetruecolor($width, $height);
imagecopyresampled($resized, $resource, 0, 0, 0, 0, $width, $height, imagesx($resource), imagesy($resource));
$resource = $resized;
return $resource;
}
resize(320, 240, "./someimage.jpg");
На практике они функционально идентичны. Основным отличием является просто парадигма ООП и процедурная парадигма; в ООП вы определяете функцию внутри класса (это называется методом), которая действует на переменную-член, тогда как в процедурной программе вы передаете эту переменную в функцию, определенную в глобальной области видимости.
Итак, в чем же преимущество переноса функции в классе вместо того, чтобы делать ее глобальной, поскольку функция все еще делает то же самое?
Основная причина, по которой вы хотите сделать это в PHP (и во многих других языках, о которых я могу подумать), это область действия. @Headspin кратко упомянул об этом. Определение функции resize
в глобальной области видимости все хорошо, пока вам не понадобится другая функция с тем же именем. Что происходит?
Обычно вы сталкиваетесь с одним из следующих решений:
- (Хорошо.) Ваш язык поддерживает перегрузку функций, поэтому вы не должны беспокоиться об этом, пока ваши аргументы отличаются.
- (Плохо.) Ваш язык не поддерживает перегрузку функций (или ваши аргументы должны быть идентичны), поэтому вы прибегаете к подробным именам (например,
resize_image
, resize_container
) и т. Д.
- (Все еще плохо.) Вы начинаете использовать пространства имен для разделения ваших глобальных функций.
- (Ужасно.) Ваша функция принимает в качестве аргумента все что угодно и становится горячим, раздутым беспорядком операторов if / then или блоков switch / case для каждого типа переменной, который она будет обрабатывать.
Моя основная причина для инкапсуляции функции в PHP состоит в том, чтобы избежать конфликтов имен, делая код более интуитивным и более легким для понимания. У меня может быть метод изменения размера в моем Image
классе, и один в моем Container
классе, и, возможно, другой в классе test
или что-то в этом роде, и ни один из них не будет конфликтовать друг с другом. Читая код, я знаю, что Image->resize()
вызывает метод в классе Image
и ничего больше.
Отсутствие конфликтов имен открывает еще несколько возможностей, таких как перебор группы объектов, имеющих общее имя метода. (Здесь вступают в игру интерфейсы; читайте о них.) Вы можете сделать много интересных вещей.
Полагаю, все, надеюсь, это поможет. Ниже приведена версия TL; DR.
Инкапсуляция одной функции в классе предотвращает конфликты именования для похожих функций, не прибегая к пространствам имен, перегрузке функций или переименованию функций. Таким образом, если у вас есть одна функция, которая выполняет общую задачу, может быть лучше создать класс для каждого типа переменной, который обрабатывается функцией, и преобразовать функцию в метод класса.