遍历从同一 class 继承的不同对象时的 C# 体系结构问题
C# architecture question when iterating through different objects inherited from the same class
对不起,我真的找不到一个明确的方法来快速解释它。
我正在做一个生成 Spheres
和 Triangles
的项目,我让它们继承自 class Objet
并将它们存储在 List<Objet>
.
现在我需要遍历这些对象(使用 foreach
),我想在此循环中使用它们的函数 getNormale(???)
。
问题是 class 球体需要两个参数,而 class 三角形不需要...
我找到了两种方法,但我不知道该用哪一种,如果有更好的方法:
- 将抽象函数
getNormale(u, v)
放入classObjet
并覆盖它,问题是Triangle.getNormale(u,v)
并不真正需要那些参数。
- 将
Sphere
和 Triangle
放在两个不同的列表中,List<Sphere>
和 List<Triangle>
遍历每个列表并调用 getNormale(u,v)
和 getNormale()
分别。我不太喜欢这个答案,因为如果我决定添加其他 classes 继承 Objet
我将需要修改这个循环...
您可以检查 cast 并以一种或另一种方式调用它。不需要在祖先中拥有虚拟版本
static void Main(string[] args)
{
List<Shape> shapes = new List<Shape>();
shapes.Add(new Triangle());
shapes.Add(new Sphere());
foreach (var shape in shapes)
{
_ = (shape is Triangle) ?
((Triangle)shape).GetNormale() :
((Sphere)shape).GetNormale(0, 0);
}
Console.ReadLine();
}
由于 getNormale
Sphere
需要 2 个参数,Triangle
需要 0 个参数,因此它们之间的关系不足以在 [=15] 中存储 getNormale
的实现=] class。如果有多个 classes 允许 getNormale
的空参数列表,您可以为此使用 sub-class,同样如果有多个 classes 允许 2 个参数对于 getNormale
也可以是它自己的 subclass.
您可以使用 is
运算符来区分这两个对象,并在对它们调用适当的 getNormale
方法之前将它们转换为适当的 class
foreach(var shape in shapes)
{
string normale;
if(shape is Triangle)
{
normale = ((Triange)shape).getNormale();
}
else if(shape is Sphere)
{
normale = ((Sphere)shape).getNormale(u,v);
}
Console.WriteLine($"Normale: {normale}");
}
或者,如果u
和v
是与对象本身相关的参数(可能u是周长,v是半径),你可以在初始化时知道它们,它们应该存储为 Sphere
class 中的字段。在这种情况下,您可以不带任何参数调用 getNormale
,因为您的 Sphere
class 已经可以访问 u
和 v
首先,您真的应该创建一个名为 shape
的抽象 class,Spheres
和 Triangles
都应从中继承。然后添加到 shape
方法 getNormale()
创建 List<shape>
而不是 List<Object>
。调用你的基数 class Object
非常混乱,你应该总是让基数 class 尽可能准确地描述派生的
现在,针对问题本身。 It is impossible to override a method with different parameters 这就是您的全部问题。这就是我建议的原因,这实际上取决于您的参数的使用,将参数放入构造函数中,并允许通过 set
方法/ 属性.
更改它们
这是处理此类问题的常用方法。
如果参数不适合成为classes 属性那么你就没有了。您将需要放弃将它们一起调用,而是坚持使用 List<object>
,检查每个对象的类型,并相应地获取 Normale,每个类型都有自己的方法和参数。切勿使用冗余参数。这可能非常令人困惑。
double normale;
ICollection<Object> shapes = new List<object>();
//add you shapes here
foreach var shape in shapes{
if(shape is Spheres)
{
normale = ((Spheres)shape).getNormale(u, v);
}
else
{
normale = ((Triangles )shape).getNormale();
}
}
您的目标应该是能够迭代您的集合作为基础 class Objet,并且能够在每个对象上调用 GetNormale()(或使用条件逻辑来确定您是否有 Sphere 并调用更具体的方法来自更专业的派生 class).
在 C# 中,使用 'virtual' 关键字作为基础 class 中可以重写的方法,'override' 关键字用于声明派生 [=24] 中的方法=](如果您在派生 class 中有一个具有不同签名的类似方法,则无需重写,因为将被视为单独的)。
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
Objet o1 = new Objet("o");
Sphere s1 = new Sphere("s", 10);
Triangle t1 = new Triangle("t", 5);
// The collection type is Objet, but you can add derived types
List<Objet> Objets = new List<Objet> { o1, s1, t1 };
foreach (Objet o in Objets)
{
if (o.GetType().Name == "Sphere")
{
// Could use 'if (o is Sphere)' ;)
// Special treatment for spheres
Sphere s = (Sphere)o;
s.GetNormale("Foo", "Bar");
}
else
{
// Could just call this for every item
o.GetNormale();
}
}
}
public class Objet
{
public string Name {get; set;}
public Objet()
{
}
public Objet(string name)
{
Name = name;
}
public virtual void GetNormale() =>
Console.WriteLine(String.Format("Objet prints: {0}", Name));
}
public class Triangle : Objet
{
public Triangle(string name, int side) : base(name)
{
Side = side;
}
public int Side {get; set;}
// Override the base class method
public override void GetNormale() =>
Console.WriteLine(String.Format("Triangle prints: {0}", Side));
}
public class Sphere : Objet
{
public Sphere(string name, int circumference) : base(name)
{
Circumference = circumference;
}
public int Circumference {get; set;}
// Method signature is different, no override required
public void GetNormale(string u, string v) =>
Console.WriteLine(String.Format("Sphere prints: {0} & {1} & {2}", Circumference, u, v));
}
}
// Output
// Objet prints: o
// Sphere prints: 10 & Foo & Bar
// Triangle prints: 5
这称为 'polymorphism',您可以在其中引用一个对象,因为它是基础 class 或派生的 class,具体取决于具体情况。
尝试阅读 'SOLID software design principles',它为 class 继承提供 best-practice 建议。
对不起,我真的找不到一个明确的方法来快速解释它。
我正在做一个生成 Spheres
和 Triangles
的项目,我让它们继承自 class Objet
并将它们存储在 List<Objet>
.
现在我需要遍历这些对象(使用 foreach
),我想在此循环中使用它们的函数 getNormale(???)
。
问题是 class 球体需要两个参数,而 class 三角形不需要...
我找到了两种方法,但我不知道该用哪一种,如果有更好的方法:
- 将抽象函数
getNormale(u, v)
放入classObjet
并覆盖它,问题是Triangle.getNormale(u,v)
并不真正需要那些参数。 - 将
Sphere
和Triangle
放在两个不同的列表中,List<Sphere>
和List<Triangle>
遍历每个列表并调用getNormale(u,v)
和getNormale()
分别。我不太喜欢这个答案,因为如果我决定添加其他 classes 继承Objet
我将需要修改这个循环...
您可以检查 cast 并以一种或另一种方式调用它。不需要在祖先中拥有虚拟版本
static void Main(string[] args)
{
List<Shape> shapes = new List<Shape>();
shapes.Add(new Triangle());
shapes.Add(new Sphere());
foreach (var shape in shapes)
{
_ = (shape is Triangle) ?
((Triangle)shape).GetNormale() :
((Sphere)shape).GetNormale(0, 0);
}
Console.ReadLine();
}
由于 getNormale
Sphere
需要 2 个参数,Triangle
需要 0 个参数,因此它们之间的关系不足以在 [=15] 中存储 getNormale
的实现=] class。如果有多个 classes 允许 getNormale
的空参数列表,您可以为此使用 sub-class,同样如果有多个 classes 允许 2 个参数对于 getNormale
也可以是它自己的 subclass.
您可以使用 is
运算符来区分这两个对象,并在对它们调用适当的 getNormale
方法之前将它们转换为适当的 class
foreach(var shape in shapes)
{
string normale;
if(shape is Triangle)
{
normale = ((Triange)shape).getNormale();
}
else if(shape is Sphere)
{
normale = ((Sphere)shape).getNormale(u,v);
}
Console.WriteLine($"Normale: {normale}");
}
或者,如果u
和v
是与对象本身相关的参数(可能u是周长,v是半径),你可以在初始化时知道它们,它们应该存储为 Sphere
class 中的字段。在这种情况下,您可以不带任何参数调用 getNormale
,因为您的 Sphere
class 已经可以访问 u
和 v
首先,您真的应该创建一个名为 shape
的抽象 class,Spheres
和 Triangles
都应从中继承。然后添加到 shape
方法 getNormale()
创建 List<shape>
而不是 List<Object>
。调用你的基数 class Object
非常混乱,你应该总是让基数 class 尽可能准确地描述派生的
现在,针对问题本身。 It is impossible to override a method with different parameters 这就是您的全部问题。这就是我建议的原因,这实际上取决于您的参数的使用,将参数放入构造函数中,并允许通过 set
方法/ 属性.
这是处理此类问题的常用方法。
如果参数不适合成为classes 属性那么你就没有了。您将需要放弃将它们一起调用,而是坚持使用 List<object>
,检查每个对象的类型,并相应地获取 Normale,每个类型都有自己的方法和参数。切勿使用冗余参数。这可能非常令人困惑。
double normale;
ICollection<Object> shapes = new List<object>();
//add you shapes here
foreach var shape in shapes{
if(shape is Spheres)
{
normale = ((Spheres)shape).getNormale(u, v);
}
else
{
normale = ((Triangles )shape).getNormale();
}
}
您的目标应该是能够迭代您的集合作为基础 class Objet,并且能够在每个对象上调用 GetNormale()(或使用条件逻辑来确定您是否有 Sphere 并调用更具体的方法来自更专业的派生 class).
在 C# 中,使用 'virtual' 关键字作为基础 class 中可以重写的方法,'override' 关键字用于声明派生 [=24] 中的方法=](如果您在派生 class 中有一个具有不同签名的类似方法,则无需重写,因为将被视为单独的)。
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
Objet o1 = new Objet("o");
Sphere s1 = new Sphere("s", 10);
Triangle t1 = new Triangle("t", 5);
// The collection type is Objet, but you can add derived types
List<Objet> Objets = new List<Objet> { o1, s1, t1 };
foreach (Objet o in Objets)
{
if (o.GetType().Name == "Sphere")
{
// Could use 'if (o is Sphere)' ;)
// Special treatment for spheres
Sphere s = (Sphere)o;
s.GetNormale("Foo", "Bar");
}
else
{
// Could just call this for every item
o.GetNormale();
}
}
}
public class Objet
{
public string Name {get; set;}
public Objet()
{
}
public Objet(string name)
{
Name = name;
}
public virtual void GetNormale() =>
Console.WriteLine(String.Format("Objet prints: {0}", Name));
}
public class Triangle : Objet
{
public Triangle(string name, int side) : base(name)
{
Side = side;
}
public int Side {get; set;}
// Override the base class method
public override void GetNormale() =>
Console.WriteLine(String.Format("Triangle prints: {0}", Side));
}
public class Sphere : Objet
{
public Sphere(string name, int circumference) : base(name)
{
Circumference = circumference;
}
public int Circumference {get; set;}
// Method signature is different, no override required
public void GetNormale(string u, string v) =>
Console.WriteLine(String.Format("Sphere prints: {0} & {1} & {2}", Circumference, u, v));
}
}
// Output
// Objet prints: o
// Sphere prints: 10 & Foo & Bar
// Triangle prints: 5
这称为 'polymorphism',您可以在其中引用一个对象,因为它是基础 class 或派生的 class,具体取决于具体情况。
尝试阅读 'SOLID software design principles',它为 class 继承提供 best-practice 建议。