PHP: расширить существующий класс

Недавно Google опубликовал Google Cloud Text To Speech.

.NET Client версия Google.Cloud.TextToSpeech можно найти здесь: https://github.com/jhabjan/Google.Cloud .TextToSpeech.V1

Nuget: Install-Package JH.Google.Cloud.TextToSpeech.V1

Вот краткий пример того, как использовать клиента:

GoogleCredential credentials =
    GoogleCredential.FromFile(Path.Combine(Program.AppPath, "jhabjan-test-47a56894d458.json"));

TextToSpeechClient client = TextToSpeechClient.Create(credentials);

SynthesizeSpeechResponse response = client.SynthesizeSpeech(
    new SynthesisInput()
    {
        Text = "Google Cloud Text-to-Speech enables developers to synthesize natural-sounding speech with 32 voices"
    },
    new VoiceSelectionParams()
    {
        LanguageCode = "en-US",
        Name = "en-US-Wavenet-C"
    },
    new AudioConfig()
    {
        AudioEncoding = AudioEncoding.Mp3
    }
);

string speechFile = Path.Combine(Directory.GetCurrentDirectory(), "sample.mp3");

File.WriteAllBytes(speechFile, response.AudioContent);

1
задан hakre 25 December 2012 в 00:26
поделиться

1 ответ

То, о чем вы просили, невозможно в базовом PHP. Есть несколько способов сделать похожие вещи.

Вы можете использовать экспериментальное расширение runkit. Функции runkit_class_emancipate и runkit_class_adopt должны работать. Однако они работают с целыми классами, а не с экземплярами класса. Это, вероятно, ограничивает их полезность для вашего приложения.

Если вы пытаетесь эмулировать возможности расширяемых классов других языков, таких как Ruby и Perl, то runkit_method_add и связанные с ней функции могут быть более подходящими. Однако, опять же, они по-прежнему оперируют целыми классами.

Обычно принятый "PHP-способ" делать подобные вещи - это __call. На самом деле, с помощью анонимных функций в 5.3 вы можете сделать что-то вроде...

class Bar {
    public function say($thing) {
        echo "Bar::say says: $thing\n";
    }
}

class Foo extends Bar {
    private $extensions = array();

    public function addExtension($func_name, $func) {
        $this->extensions[ $func_name ] = $func;
    }

    public function __call($func_name, $arguments) {
        array_unshift($arguments, $this);
        if(array_key_exists($func_name, $this->extensions))
            call_user_func_array($this->extensions[ $func_name ], $arguments);
    }
}

$f = new Foo();
$anon = function($obj, $string){ $obj->say($string); };
$f->addExtension('example', $anon);
$f->example("Hello, world!");

Вы заметите в __call и в создании анонимной функции, что первый аргумент становится экземпляром. Это потому, что реализация анонимных функций в PHP 5.3 не может ссылаться на $this. Это также означает, что они не могут ссылаться на защищенные или приватные члены класса. Это можно исправить, клонировав экземпляр и используя Reflection для раскрытия защищенных и закрытых членов. Пример реализации см. в этом комментарии на странице руководства по анонимным функциям.

Из-за ограничений PHP вы не можете напрямую присвоить анонимную функцию свойству и вызвать ее. Этот пример не будет работать:

class WillNotWork {
    public $fatal_error;
}

$broken = new WillNotWork();
$anon = function($arg) { echo "I'm about to create a {$arg} error!"; };
$broken->fatal_error = $anon;
$broken->fatal_error("fatal");
// Fatal error: Call to undefined method WillNotWork::fatal_error()
1
ответ дан 2 September 2019 в 23:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: