私はジェネリック コレクション クラス テンプレートに取り組んでいます。たとえばList(T)
、php の遅延静的バインディングのようなことができるようにしたいと考えています。いくつかの単純化されたサンプル コードで最もよく説明されるかもしれません。このコードは dmd でそのままコンパイルできますが、希望どおりにするには少し変更する必要があります。
module main;
import std.stdio;
import std.string;
class List(T)
{
private T[] _list;
public void append(T t)
{
_list ~= t;
}
// this is where some help is needed...
public List select(bool delegate(T t) dg)
{
// auto should be whatever subclass of List(T) is calling this method.
auto result = new List!T();
foreach(t; _list)
{
if (dg(t)) result.append(t);
}
return result;
}
int opApply(int delegate(ref T) dg)
{
int result = 0;
for (int i = 0; i < _list.length; i++)
{
result = dg(_list[i]);
if (result)
break;
}
return result;
}
}
enum Gender
{
MALE,
FEMALE,
SECRET
}
class Person
{
private string _firstName;
private string _lastName;
private string _email;
private Gender _gender;
@property public string firstName() {return _firstName;}
@property public string lastName() {return _lastName;}
@property public string email() {return _email;}
@property public Gender gender() {return _gender;}
public this()
{
}
public this(string firstName, string lastName, Gender gender = Gender.SECRET, string email = "info@example.com")
{
this();
this._firstName = firstName;
this._lastName = lastName;
this._gender = gender;
this._email = email;
}
override public string toString()
{
if (email.length > 0)
{
return "%s %s <%s>".format(firstName, lastName, email);
}
else
{
return "%s %s".format(firstName, lastName);
}
}
}
class PeopleList : List!Person
{
// I would like to be able to make this: public PeopleList selectByGender(Gender gender)
public List!Person selectByGender(Gender gender)
{
return select(p => p.gender == gender);
}
}
void main(string[] args)
{
auto people = new PeopleList();
people.append(new Person("Kris", "Herlaar", Gender.MALE));
people.append(new Person("John", "Doe", Gender.MALE));
people.append(new Person("Steve", "Wozniak", Gender.MALE));
people.append(new Person("Walter", "Bright", Gender.MALE));
people.append(new Person("Amelia", "Earhart", Gender.FEMALE, null));
people.append(new Person("Susan", "Anthony", Gender.FEMALE, null));
foreach(p; people.selectByGender(Gender.FEMALE))
{
writeln(p);
}
}
コメントアウトされた宣言が正しいように、 a ではなくのPeopleList.select
インスタンスも返すことを確認するにはどうすればよいですか?PeopleList
List!Person
selectByGender
おそらくObject.factory(this.classinfo.name)
実装内でモックを作成して、実際に正しいタイプのインスタンスを取得できますresult
が、宣言された戻り値の型には役立たないと思います。
メソッドの連鎖を可能にしたいので、呼び出しList(T).select
ているサブクラスのインスタンスを返すことができるようにするコンパイラが必要です。ネストされたテンプレートを使用して実行できると思いますが、それを実現することはできませんでした。エレガントに見えることは言うまでもなく、コンパイルされます。
受け取ったフィードバックに対する追加情報
私は、実生活std.algorithm
でのことを知っています。filter
このコードは実際のユースケースを表すものではなく、D とそのテンプレートの機能/制限をさらに学習するための思考実験です。