我需要帮助来理解抽象类的用法。我有一个名为WorldObject
的抽象类:
public abstract class WorldObject
{
public Vector3 position;
}
我有许多继承自此的类,例如Building
和Tree
。
我想创建一个循环通过List
的WorldObjects
的方法,并向我返回最接近的方法。我希望能够对我的所有WorldObjects
类型使用此方法,但无法使其正常工作:
public List<Building> buildings = new List<Building>();
public List<Tree> trees= new List<Tree>();
private void GoToClosestBuilding()
{
var target = GetClosestWorldObject(buildings); //Error: Cannot convert building to WorldObject
}
Vector3 GetClosestWorldObject(List<WorldObject> objects)
{
//...
}
[当我尝试将Building
或Tree
列表传递给我的方法时,它返回错误,无法在Building
和WorldObject
之间进行转换,依此类推。
如何构造代码,使类似的代码行得通?
List<Building>
与List<WorldObject>
的分配不兼容,因为那样就可以这样做
List<WorldObject> worldObjects = buildings; // Not possible!
worldObjects.Add(tree); // Legal
worldObjects.Add(tree);
完全合法。但是,由于worldObjects
将引用建筑物列表,因此您将不能将其添加为树!
但是,您可以将方法的签名更改为
Vector3 GetClosestWorldObject(IEnumerable<WorldObject> objects)
{
...
}
现在,这有效
var target = GetClosestWorldObject(buildings);
因为可枚举被声明为
public interface IEnumerable<out T> : IEnumerable
{
IEnumerator<T> GetEnumerator();
}
out
关键字指出,T
仅出现在外位置,即作为返回值或外参数。这使类型成为协变。
您可以使用通用函数。
Vector3 GetClosestWorldObject<T>(List<T> objects) where T: WorldObject
{
// ...
}
List<Building>
与List<WorldObject>
的分配不兼容,因为那样就可以这样做
worldObjects.Add(tree);
这是完全合法的。但是,由于该列表引用了建筑物列表,因此您不能将其添加为树!
但是,您可以将方法的签名更改为
Vector3 GetClosestWorldObject(IEnumerable<WorldObject> objects)
{
...
}
现在,这有效
var target = GetClosestWorldObject(buildings);
因为可枚举被声明为
public interface IEnumerable<out T> : IEnumerable
{
IEnumerator<T> GetEnumerator();
}
out
的关键字T
仅出现在外位置,即作为返回值或out参数。