dmd 2.061 yeni bir olanak getirdi: User Defined Attributes (UDA).
UDA'ları başka dillerden bilen programcılar çok sevindiler. :) Benim hiç deneyimim yok. Şimdilik D forumlarından ve şu taslaktan öğrenilebiliyor:
https://dl.dropbox.com/u/18386187/attribute.html#uda
Bu olanak şunları getiriyor:
-
Türlere (ve değişkenlere) kullanıcının tanımladığı nitelikler vermek. Bu nitelikler @property söz dizimiyle örneğin @ÖzelNitelik diye yazılıyor.
-
Bu nitelikleri derleme zamanında sorgulamak ve duruma göre kod yazmak.
İkinci maddeden anlaşılacağı gibi UDA bütünüyle derleme zamanında işleyen bir olanak. Birden fazla nitelik verilebiliyor. Nitelikler çokuzlu olarak elde ediliyorlar.
Aşağıdaki program @GüvenleKopyalanabilir diye bir nitelik tanımlıyor, onu Yapı isimli türe veriyor (ama BaşkaYapı'ya vermiyor):
import std.stdio;
/* Başka türleri ve nesneleri nitelendirirken kullanacağımız bir tür
* tanımlıyoruz. Bu türün üye değişkenleri de olabilir ama bu türün isminin
* yeterli olduğunu düşünüyorum. (Ek olarak, bu konuda daha önce hiç deneyimim
* de yok. :p)
*
* Adından anlaşıldığı gibi, bu niteliği güvenle kopyalanabilen türleri
* nitelemek için kullanacağız.
*/
struct GüvenleKopyalanabilir
{}
/* Bu, yukarıdaki niteliğe sahip olan bir tür. Aşağıdaki ilk satırın tek
* yaptığı, Yapı'nın GüvenleKopyalanabilir niteliğine sahip olduğunu
* belirlemek.
*
* Nitelikler aşağıda görüldüğü gibi __traits(getAttributes) ile elde
* edilebiliyorlar.
*/
@GüvenleKopyalanabilir
struct Yapı
{}
/* Bu yapını GüvenleKopyalanabilir niteliği bulunmuyor.
*/
struct BaşkaYapı
{}
/* Bu şablonun bu konuyla doğrudan ilgisi yok ve hatta bunun Phobos'ta zaten
* olmasını beklerim. (Fazla aramadım; belki de vardır).
*
* Tek yaptığı, türün belirtilen niteliğe sahip olup olmadığını belirlemek.
*/
template niteliğiVar_mı(T, SorgulananNitelik)
{
/* Bu, yalnızca bu şablon tarafından kullanılan bir yerel işlev. */
bool var_mı()
{
/* Kullanıcının tanımladığı nitelikler __traits(getAttributes) ile
* öğreniliyor. Bu kodun yaptığı, türün nitelikleri üzerinde ilerlemek
* ve aranan niteliğe rastlanırsa true döndürmek.
*/
foreach (t; __traits(getAttributes, T)) {
if (typeid(t) is typeid(SorgulananNitelik)) {
return true;
}
}
return false;
}
enum niteliğiVar_mı = var_mı();
}
/* Bu, kullanıcının yazmış olduğu bir işlev. Nitelik vermenin ve onları
* sorgulamanın yararını gösteriyor.
*/
void foo(T)(T parametre)
{
/* Şablonlar gibi, nitelikler de bütünüyle derleme zamanında işleyen bir
* olanak. 'static if'ten ve yukarıda tanımladığımız 'niteliğiVar_mı'dan
* yararlanarak T'nin niteliğini sorguluyoruz ve foo() işlevini buna uygun
* olarak tanımlıyoruz.
*/
static if (niteliğiVar_mı!(T, GüvenleKopyalanabilir)) {
writefln("'%s' güvenle kopyalanabilirmiş. Kopyalıyorum.", T.stringof);
T kopyası = parametre;
/* ... algoritmanın gerisi ... */
} else {
writefln("'%s' kopyalanamıyormuş. Başka bir algoritma kullanıyorum.",
T.stringof);
// ... kopyasını almayan başka algoritma ...
}
}
void main()
{
auto y = Yapı();
foo(y);
auto by = BaşkaYapı();
foo(by);
}
foo() işlevi main içinde iki farklı türle kullanılıyor. Bu türlerden birisi @GüvenleKopyalanabilir niteliğine sahip olduğu için foo()'nun gerçekleştirimi onun için farklı oluyor:
''Yapı' güvenle kopyalanabilirmiş. Kopyalıyorum.
'BaşkaYapı' kopyalanamıyormuş. Başka bir algoritma kullanıyorum.'
Ben yukarıda 'struct GüvenleKopyalanabilir {}' diye tanımlanmış olan başlı başına bir tür kullandım. Önerilen o... Buna rağmen, belki de daha kolay oldukları için temel türlerden olan değerler bile nitelik olabiliyorlar. Aşağıdaki program bunu gösteriyor. Ek olarak, birden fazla nitelik de verilebiliyor:
import std.stdio;
/* Bu yapının nitelikleri sıradan iki değer. */
@(42, "merhaba")
struct Yapı
{}
void foo(T)(T nesne)
{
/* Nitelikler çokuzlu olarak elde ediliyorlar. */
enum nitelikler = __traits(getAttributes, T);//
/* İspatlayalım: */
static assert(__traits(getAttributes, T)[0] == 42);
static assert(__traits(getAttributes, T)[1] == "merhaba");
}
void main()
{
Yapı a = Yapı();
foo(a);
}
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]