Подтвердить что ты не робот

Насколько уникален PHP __autoload()?

PHP __autoload() (документация) мне очень интересна. Вот как это работает:

  • Вы пытаетесь использовать класс, например new Toast_Mitten() (footnote 1)
  • Класс не загружен в память. PHP откидывает кулак, чтобы выбить вас с ошибкой.
  • Он останавливается. "Подождите, - говорит он." Там определена функция __autoload()". Он запускает его.
  • В этой функции вы каким-то образом сопоставили строку Toast_Mitten с classes/toast_mitten.php и сказали ей, что требуется этот файл. Он делает.
  • Теперь класс находится в памяти, и ваша программа продолжает работать.

Преимущество памяти: вы загружаете только нужные классы. Преимущество терминологии: вы можете остановить включение большого количества файлов во всем мире и просто включить свой автозагрузчик.

Все становится особенно интересным, если

1) Ваш __autoload() имеет автоматический способ определения пути и имени файла из имени класса. Например, возможно, все ваши классы находятся в classes/ и Toast_Mitten будут в classes/toast_mitten.php. Или, возможно, вы называете такие классы, как Animal_Mammal_Weasel, который будет находиться в classes/animal/mammal/animal_mammal_weasel.php.

2) Вы используете метод factory для получения экземпляров вашего класса.

$Mitten = Mitten::factory('toast');

Метод Mitten:: factory может сказать себе: "Посмотрим, у меня есть подкласс, называемый Toast_Mitten()? Если это так, я верну его, а если нет, я просто верну общий пример о себе, стандартная рукавица. О, посмотри! __autoload() говорит мне, что есть специальный класс для тостов. ОК, вот экземпляр!"

Таким образом, вы можете начать использовать универсальную рукавицу во всем своем коде, и когда наступит день, вам нужно специальное поведение для тоста, вы просто создаете этот класс и bam! - ваш код использует он.

Мой вопрос двоякий:

  • (Факт) Имеют ли другие языки подобные конструкции? Я вижу, что Ruby имеет автозагрузку, но, похоже, вам нужно указать в заданном script, какие классы вы планируете использовать.
  • (Мнение) Является ли это слишком волшебным? Если ваш любимый язык не делает этого, вы думаете: "Эй, изящный, мы должны иметь это" или "человек, я рад, что язык X не такой неряшливый?"

1 Приношу свои извинения не англоязычным докладчикам. Это небольшая шутка. Насколько я знаю, нет такой вещи, как "топиная рукавица". Если бы это было так, это была бы рукавица для сбора горячего тоста. Возможно, у вас есть тосты в вашей родной стране?

4b9b3361

Ответ 2

  • Не используйте __autoload(). Это глобальная вещь, поэтому, по определению, она несколько зла. Вместо этого используйте spl_autoload_register(), чтобы зарегистрировать еще один автозагрузчик в вашей системе. Это позволяет использовать несколько автозагрузчиков, что довольно распространенная практика.
  • Уважать существующие соглашения. Каждая часть имени класса с именами имен является каталогом, поэтому new MyProject\IO\FileReader(); должен находиться в файле MyProject/IO/FileReader.php.
  • Магия - это зло!

    Метод Mitten:: factory может сказать себе: "Посмотрим, у меня есть подкласс под названием Toast_Mitten()? Если это так, я верну его, а если нет, я просто верну общий пример __autoload() говорит мне, что есть специальный класс для тостов. ОК, вот экземпляр!"

    Скорее такой хитрый код, используйте простой и подробный:

    try {
        $mitten = new ToastMitten();
        // or $mitten = Mitten::factory('toast');
    } catch (ClassNotFoundException $cnfe) {
        $mitten = new BaseMitten();
    }
    

Ответ 3

Я думаю, что эта функция очень удобна, и я не видел никаких функций, подобных ей. Мне также не нужны эти функции еще где.

Ответ 4

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

И, пока мы в этом. Было бы неплохо, если бы __autoload загружал любые типы символов, а не только классы: константы, функции и классы.

Ответ 5

См. Ruby Module # const_missing

Я только что узнал об этом: Ruby имеет метод в модуле с именем const_missing, который вызывается, если вы вызываете Foo::Bar и Bar еще не в памяти (хотя я полагаю, что Foo должен быть в памяти).

Этот пример в ruby-doc.org показывает способ использования этого для реализации автозагрузчика для этого модуля. Это, по сути, то, что Rails использует для загрузки новых классов модели ActiveRecord в соответствии с "Eloquent Ruby" Руса Олсена (глава 21, "Использовать метод_изменение для гибкой обработки ошибок", который также охватывает const_missing).

Он может сделать это из-за мышления "соглашение над конфигурацией": если вы ссылаетесь на модель под названием ToastMitten, если она существует, она будет находиться в app/models/toast_mitten.rb. Если бы вы могли разместить эту модель в любом месте, которое вы хотели, Rails не знал бы, где ее искать. Даже если вы не используете Rails, этот пример и пункт №1 в моем вопросе показывают, насколько полезно использовать следующие соглашения, даже если вы создаете их самостоятельно.