İsimsiz bir sınıf'bir makro s yöntemleri ile yapısal bir türü almak
Sanırım istediğimiz için yazmak bir makro tanımlar isimsiz bir sınıf ile bazı tür üyeleri veya yöntemler, ve sonra oluşturur bir örnek bu sınıfı bu statik olarak yazılan bir yapı türü olan bu yöntem, vb. Bu 2.10.0 ve üye bölümü son derece kolay yazın: makro sistemi ile mümkündür
object MacroExample extends ReflectionUtils {
import scala.language.experimental.macros
import scala.reflect.macros.Context
def foo(name: String): Any = macro foo_impl
def foo_impl(c: Context)(name: c.Expr[String]) = {
import c.universe._
val Literal(Constant(lit: String)) = name.tree
val anon = newTypeName(c.fresh)
c.Expr(Block(
ClassDef(
Modifiers(Flag.FINAL), anon, Nil, Template(
Nil, emptyValDef, List(
constructor(c.universe),
TypeDef(Modifiers(), newTypeName(lit), Nil, TypeTree(typeOf[Int]))
)
)
),
Apply(Select(New(Ident(anon)), nme.CONSTRUCTOR), Nil)
))
}
}
(9* *constructor
benim yöntem sağlar convenience trait.)
Bu makro, bize bir dize olarak anonim sınıfın türü üyesinin adını belirtmenizi sağlar:
scala> MacroExample.foo("T")
res0: AnyRef{type T = Int} = $1$$1@7da533f6
Uygun şekilde yazılmış olduğunu unutmayın. Her şey beklendiği gibi çalıştığını doğrulayın
scala> implicitly[res0.T =:= Int]
res1: =:=[res0.T,Int] = <function1>
Şimdi bir yöntem ile aynı şeyi yapmaya çalıştığımızı varsayalım:
def bar(name: String): Any = macro bar_impl
def bar_impl(c: Context)(name: c.Expr[String]) = {
import c.universe._
val Literal(Constant(lit: String)) = name.tree
val anon = newTypeName(c.fresh)
c.Expr(Block(
ClassDef(
Modifiers(Flag.FINAL), anon, Nil, Template(
Nil, emptyValDef, List(
constructor(c.universe),
DefDef(
Modifiers(), newTermName(lit), Nil, Nil, TypeTree(),
c.literal(42).tree
)
)
)
),
Apply(Select(New(Ident(anon)), nme.CONSTRUCTOR), Nil)
))
}
Ama biz çalıştığınızda, yapısal bir tip yok:
scala> MacroExample.bar("test")
res1: AnyRef = $1$$1@da12492
Ama eğer fazladan bir anonim sınıf olursak:
def baz(name: String): Any = macro baz_impl
def baz_impl(c: Context)(name: c.Expr[String]) = {
import c.universe._
val Literal(Constant(lit: String)) = name.tree
val anon = newTypeName(c.fresh)
val wrapper = newTypeName(c.fresh)
c.Expr(Block(
ClassDef(
Modifiers(), anon, Nil, Template(
Nil, emptyValDef, List(
constructor(c.universe),
DefDef(
Modifiers(), newTermName(lit), Nil, Nil, TypeTree(),
c.literal(42).tree
)
)
)
),
ClassDef(
Modifiers(Flag.FINAL), wrapper, Nil,
Template(Ident(anon) :: Nil, emptyValDef, constructor(c.universe) :: Nil)
),
Apply(Select(New(Ident(wrapper)), nme.CONSTRUCTOR), Nil)
))
}
Çalışır:
scala> MacroExample.baz("test")
res0: AnyRef{def test: Int} = $2$$1@6663f834
scala> res0.test
res1: Int = 42
Bu kullanışlı—örnek—ama neden çalıştığını anlamıyorum this,, gibi şeyler yapalım ve yazın üye sürümünü işleri de çok, ama bar
değil. Bu may not be defined behavior, ama mantıklı mı? Temiz bir şekilde yapısal bir türü (yöntemlerle) bir makro için?
CEVAP
Hadi sınıf yöntemleri dinleme görevi işlemek için değiştirmek ve bir jenerik istiyorum bunu gerektirir çünkü Gözlemci desen istemediğini söyle. Ve diyelim kullanmak istemediğini söyleuzanırsenin yüzünden miras zaten başka sınıftan sınıf devralmasını. Bunu yapmak için genel bir yol olması harika olmaz mıydıherhangi bir sınıf çok çaba olmadan takılabilir? İşte nasıl:
<?php
////////////////////
// PART 1
////////////////////
class Plugin {
private $_RefObject;
private $_Class = '';
public function __construct(&$RefObject) {
$this->_Class = get_class(&$RefObject);
$this->_RefObject = $RefObject;
}
public function __set($sProperty,$mixed) {
$sPlugin = $this->_Class . '_' . $sProperty . '_setEvent';
if (is_callable($sPlugin)) {
$mixed = call_user_func_array($sPlugin, $mixed);
}
$this->_RefObject->$sProperty = $mixed;
}
public function __get($sProperty) {
$asItems = (array) $this->_RefObject;
$mixed = $asItems[$sProperty];
$sPlugin = $this->_Class . '_' . $sProperty . '_getEvent';
if (is_callable($sPlugin)) {
$mixed = call_user_func_array($sPlugin, $mixed);
}
return $mixed;
}
public function __call($sMethod,$mixed) {
$sPlugin = $this->_Class . '_' . $sMethod . '_beforeEvent';
if (is_callable($sPlugin)) {
$mixed = call_user_func_array($sPlugin, $mixed);
}
if ($mixed != 'BLOCK_EVENT') {
call_user_func_array(array(&$this->_RefObject, $sMethod), $mixed);
$sPlugin = $this->_Class . '_' . $sMethod . '_afterEvent';
if (is_callable($sPlugin)) {
call_user_func_array($sPlugin, $mixed);
}
}
}
} //end class Plugin
class Pluggable extends Plugin {
} //end class Pluggable
////////////////////
// PART 2
////////////////////
class Dog {
public $Name = '';
public function bark(&$sHow) {
echo "$sHow<br />\n";
}
public function sayName() {
echo "<br />\nMy Name is: " . $this->Name . "<br />\n";
}
} //end class Dog
$Dog = new Dog();
////////////////////
// PART 3
////////////////////
$PDog = new Pluggable($Dog);
function Dog_bark_beforeEvent(&$mixed) {
$mixed = 'Woof'; // Override saying 'meow' with 'Woof'
//$mixed = 'BLOCK_EVENT'; // if you want to block the event
return $mixed;
}
function Dog_bark_afterEvent(&$mixed) {
echo $mixed; // show the override
}
function Dog_Name_setEvent(&$mixed) {
$mixed = 'Coco'; // override 'Fido' with 'Coco'
return $mixed;
}
function Dog_Name_getEvent(&$mixed) {
$mixed = 'Different'; // override 'Coco' with 'Different'
return $mixed;
}
////////////////////
// PART 4
////////////////////
$PDog->Name = 'Fido';
$PDog->Bark('meow');
$PDog->SayName();
echo 'My New Name is: ' . $PDog->Name;
1, Bir require_once ile dahil olabilirsin ne() PHP script üstündeki Arama. Bu sınıflar bir şey takılabilir yapmak için yükler.
Bölüm 2, Biz bir sınıf yük. Bir şey Gözlemci desen daha farklı olan Sınıf, özel bir şey yapmak zorunda değildim unutmayın.
3, etrafında olmak bizim dersimiz anahtarı nerede "" (bizim sınıf yöntemleri ve özellikleri geçersiz kılmak için izin eklentileri destekler). takılabilir Part Eğer bir web uygulaması varsa, örneğin, bir eklenti kayıt olabilir, ve burada eklentileri aktive edebilirsiniz. Dikkat edin de "Dog_bark_beforeEvent" fonksiyonu. Karma = ayarladım $'' return ifadesi önce, havlayan köpek engeller ve aynı zamanda herhangi bir olay olmazdı çünkü Dog_bark_afterEvent blok. BLOCK_EVENT eğer
Bölüm 4, Bu normal işlem kodu yok, ama aday olacağını düşünebilirsiniz ne böyle hiç çalışmaz dikkat edin. Örneğin, köpek adı olarak ilan etmez '' ama ''. Coco Fido Köpeğin derdi yok '' ama ''. Woof meow Ve köpeğin adı daha sonra bakmak istediğinizde, onu bulun 'Farklı' yerine ''. Coco Tüm bu geçersiz kılar Part 3 sağlandı.
Bu iş nasıl olacak? Hadi ekarte eval() (herkes diyor ki "") kötülük ve Gözlemci desen değil bu kural. Yani, işler böyle yöntemleri ve özellikleri Köpek sınıfı tarafından kullanılan içermeyen sinsi boş sınıf Takılabilir denir. Bu oluşur bu yana, bu nedenle, sihirli yöntemler bizim için meşgul olacak. Bu parçaları 3 ve 4'te biz nesne Takılabilir sınıfından türetilmiş, Köpek sınıfın kendisi değil karışıklık. Bunun yerine, Eklenti sınıfı"," bizim için nesne. Köpek dokunmadan yapalım Eğer desen bir tür olup olmadığını bilmiyorum -- bana bildirin lütfen.)
Nasıl jenerik T türü bir sınıf örneği ...
Python ile bir sınıf adını almak...
Kısayol aranabilir bir sınıf yöntemler...
Uzatma yöntemleri genel olmayan statik...
Nasıl paketi olmadan bir sınıf adını a...