일반 콜렉션 클래스 템플릿에서 작업하고 있습니다. List(T)
어디에서 PHP의 후기 정적 바인딩과 같은 작업을 수행 할 수 있습니다. 단순화 된 샘플 코드로 가장 잘 설명 될 수 있습니다. 이 코드는 dmd에서와 같이 정상적으로 컴파일되지만 원하는 방식으로 변경해야합니다.후기 정적 바인딩 d
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 = "[email protected]")
{
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
대신
selectByGender
의 주석 선언이 올바른지 그래서
List!Person
의 인스턴스를 반환하는지 확인하고 가겠어요 어떻게
?
구현 내에서 Object.factory(this.classinfo.name)
을 조롱하고 실제로 result
에 대한 올바른 유형의 인스턴스를 얻을 수는 있지만 선언 된 반환 유형에 도움이되지 않을 것이라고 생각합니다.
가능한 체인 메서드를 만들고 싶습니다 그래서 어떤 하위 클래스 호출 인스턴스를 반환하도록 컴파일러가 필요합니다 List(T).select
중첩 된 템플릿으로 수행 할 수 있지만 상상할 수 없을 것이라고 상상해 봅니다. 컴파일할만한 것이 무엇인지 생각해보십시오.
내가 실제 생활에서 std.algorithm
과 filter
의 알고받은 의견을 회신
추가 정보; 이 코드는 실제 유스 케이스를 나타내지는 않지만 D와 그 템플릿의 능력/한계에 대해 더 많이 배우려는 생각의 실험입니다.
일명 자바의 클론과 비슷한 것을 원한다. 현재 (런타임) 유형으로 새 인스턴스를 만듭니다. –
기술적으로 "정적 인"정적 바인딩이 아니라는 것을 알고 있습니다.하지만 나중에 복제하는 것은 아닙니다. 난 그냥 슈퍼 클래스 메서드에서 하위 클래스 형식을 반환하려면, 어디 수퍼 클래스 정말 하위 형식에 대해 알고 싶지 않아요. – Kris
어쩌면 당신은 C++ STL 접근법을 사용하고 컨테이너에 상속 대신 컴포지션을 적용해야 할 것입니다. 이것은 당신의 문제를 해결할 것입니다. 또는 상속 가능한 컨테이너가 필요한 좋은 이유가 있습니까? – RedX