RAII deyim bir kod düzeyinde bir stand-bir finally
bloğu için sunar. (Ler) çağrılabilir tutan bir sınıf oluşturmak. Destuctor olarak, çağrılabilir (ler) diyoruz.
class Finally {
# could instead hold a single block
public $blocks = array();
function __construct($block) {
if (is_callable($block)) {
$this->blocks = func_get_args();
} elseif (is_array($block)) {
$this->blocks = $block;
} else {
# TODO: handle type error
}
}
function __destruct() {
foreach ($this->blocks as $block) {
if (is_callable($block)) {
call_user_func($block);
} else {
# TODO: handle type error.
}
}
}
}
Coordination
PHP değişkenleri için blok kapsama sahip değildir, bu nedenle Finally
fonksiyon çıkmadan ya da (küresel alanda) kapatma sırası kadar tekme unutmayın. Örneğin, aşağıdaki gibidir:
try {
echo "Creating global Finally.\n";
$finally = new Finally(function () {
echo "Global Finally finally run.\n";
});
throw new Exception;
} catch (Exception $exc) {}
class Foo {
function useTry() {
try {
$finally = new Finally(function () {
echo "Finally for method run.\n";
});
throw new Exception;
} catch (Exception $exc) {}
echo __METHOD__, " done.\n";
}
}
$foo = new Foo;
$foo->useTry();
echo "A whole bunch more work done by the script.\n";
will result in the output:
Creating global Finally.
Foo::useTry done.
Finally for method run.
A whole bunch more work done by the script.
Global Finally finally run.
$this
PHP 5.3 kapanışları erişemiyor $this
bazı nihayet-blok içinde örnek üyeleri erişmek için ekstra bir değişken gerekir, böylece (5.4 sabit).
class Foo {
function useThis() {
$self = $this;
$finally = new Finally(
# if $self is used by reference, it can be set after creating the closure
function () use ($self) {
$self->frob();
},
# $this not used in a closure, so no need for $self
array($this, 'wibble')
);
/*...*/
}
function frob() {/*...*/}
function wibble() {/*...*/}
}
Private and Protected Fields
Muhtemelen PHP 5.3, bu yaklaşımla büyük sorun nihayet kapanması bir nesnenin özel ve korunan alanları erişemiyor. $this
erişme gibi, bu konu PHP 5.4 giderilmiştir. Artefacto başka bir yerde bu sitede bu çok konu hakkında sorulan bir soruya verdiği answer gösterdiği gibi, şimdi, private and protected properties, referanslar kullanarak erişilebilir.
class Foo {
private $_property='valid';
public function method() {
$this->_property = 'invalid';
$_property =& $this->_property;
$finally = new Finally(function () use (&$_property) {
$_property = 'valid';
});
/* ... */
}
public function reportState() {
return $this->_property;
}
}
$f = new Foo;
$f->method();
echo $f->reportState(), "\n";
Private and protected methods yansıma kullanarak ulaşılabilir. Aslında halka açık olmayan özelliklerine erişmek için aynı tekniği kullanabilirsiniz, ancak referanslar daha basit ve hafif. anonymous functions için PHP kılavuzu sayfada bir yorumda, Martin Pärtel kamu erişimi olmayan kamu alanları açılır bir FullAccessWrapper
sınıfının bir örnek verir. Ben (bunun için önceki iki bağlantılara bakın) burada yeniden, ama burada bunu kullanmak istiyorum nasıl olmaz:
class Foo {
private $_property='valid';
public function method() {
$this->_property = 'invalid';
$self = new FullAccessWrapper($this);
$finally = new Finally(function () use (&$self) {
$self->_fixState();
});
/* ... */
}
public function reportState() {
return $this->_property;
}
protected function _fixState() {
$this->_property = 'valid';
}
}
$f = new Foo;
$f->method();
echo $f->reportState(), "\n";
try/finally
try
blok en az bir gerekli catch
. Sadece isterseniz try/finally
, olmayan bir Exception
(PHP kodu {[(4 türetilmiş değil bir şey atmak değil) yakalar catch
blok eklemek ]}) veya yakalanan özel yeniden atmak. Eski durumda, ben StdClass
anlamına gelen bir deyim "bir şey yakalamak yok" gibi yakalıyor öneririz. Yöntemlerde, mevcut sınıf alıcı da "bir şey yakalamak yok" demek için kullanılan olabilir, fakat StdClass
dosya ararken bulmak için basit ve kolaydır.
try {
$finally = new Finally(/*...*/);
/* ... */
} catch (StdClass $exc) {}
try {
$finally = new Finally(/*...*/);
/* ... */
} catch (RuntimeError $exc) {
throw $exc
}