我正在开发一个通用集合类模板,让我们说一下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);
}
}
我将如何确保它PeopleList.select
也会返回一个实例PeopleList
而不是 aList!Person
以便注释掉的声明selectByGender
是正确的?
我可能可以Object.factory(this.classinfo.name)
在实现内部进行模拟并实际获得正确的实例类型,result
但我认为这对声明的返回类型没有帮助。
我想让链接方法成为可能,所以我需要编译器允许我返回正在调用的任何子类的实例List(T).select
我想它可以使用嵌套模板来完成,但无法想出任何会编译,更不用说看起来很优雅了。
回复收到的反馈的附加信息
我知道std.algorithm
并且filter
在现实生活中;这段代码并不代表一个实际的用例,而是一个思想实验,以了解更多 D 及其模板的能力/限制。