SORU
17 Ocak 2013, PERŞEMBE


İ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
1 HAZİRAN 2009, PAZARTESİ


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.)

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Tome Rodrigo

    Tome Rodrigo

    9 Temmuz 2006
  • VitalyzdTv

    VitalyzdTv

    7 AĞUSTOS 2011
  • Vsauce

    Vsauce

    30 Temmuz 2007