假设我有一个继承自 Point2D 的Class Point3D 以及从 Drawing2D 继承的Class Drawing3D 。
我希望Drawing2D和Drawing3D这两个类都具有相同的属性名称Points ,它将是Drawing2D的Point2D列表,以及Drawing3D的Point3D列表。
具有相同的属性名称,我希望Drawing3D可以在属性Points上受益于Drawing2D方法。 事情是我不能使用覆盖,因为类型不同。关键字 new 不起作用,因为Drawing3D似乎有2个属性点(Point2D列表和Point3D列表)。 在Drawing3D上使用基本方法,它将通过Point2D列表。
我的2D课程:
class Point2D
{
public int X { get; set; }
public int Y { get; set; }
public Point2D(int x, int y)
{
X = x;
Y = y;
}
public virtual void Print()
{
Console.WriteLine($"2D Point: [{X}, {Y}]");
}
}
class Drawing2D
{
public string Name { get; set; }
public virtual List<Point2D> Points { get; set; }
public Drawing2D(string name)
{
Name = name;
Points = new List<Point2D>();
}
public void Print()
{
Console.WriteLine($"Drawing name: {Name}");
foreach (var point in Points)
point.Print();
}
}
基于2D类的我的3D类
class Point3D:Point2D
{
public int Z { get; set; }
public Point3D(int x, int y, int z):base(x,y)
{
Z = z;
}
public override void Print()
{
Console.WriteLine($"3D Point: [{X}, {Y}, {Z}]");
}
}
class Drawing3D : Drawing2D
{
public new List<Point3D> Points { get; set; }
public Drawing3D(string name) : base(name)
{
Points = new List<Point3D>();
}
}
我的主程序
class Program
{
static void Main(string[] args)
{
Drawing3D myDrawing = new Drawing3D("Sketch");
myDrawing.Points.Add(new Point3D(1, 2, 3));
myDrawing.Points.Add(new Point3D(4, 5, 6));
myDrawing.Print();
Console.ReadKey();
}
}
结果是它不打印任何一点。基本方法Print()遍历Point2D列表,而不是Point3D。
希望你们能帮助我。 我喜欢优雅的代码,可能是我的方法不正确...
干杯
答案 0 :(得分:1)
如果您必须为上述示例做,那么您可以这样做。
public abstract class Point
{
public abstract void Print();
}
class Point2D : Point
{
public int X { get; set; }
public int Y { get; set; }
public Point2D(int x, int y)
{
X = x;
Y = y;
}
public override void Print()
{
Console.WriteLine($"2D Point: [{X}, {Y}]");
}
}
class Point3D : Point2D
{
public int Z { get; set; }
public Point3D(int x, int y, int z) : base(x, y)
{
Z = z;
}
public override void Print()
{
Console.WriteLine($"3D Point: [{X}, {Y}, {Z}]");
}
}
class Drawing<T> where T:Point
{
public string Name { get; set; }
public virtual List<T> Points { get; set; }
public Drawing(string name)
{
Name = name;
Points = new List<T>();
}
public void Print()
{
Console.WriteLine($"Drawing name: {Name}");
foreach (var point in Points)
point.Print();
}
}
class Drawing3D : Drawing<Point3D>
{
public Drawing3D(string name) : base(name)
{
Name = name;
}
}
class Drawing2D : Drawing<Point2D>
{
public Drawing2D(string name) : base(name)
{
Name = name;
}
}
答案 1 :(得分:1)
在你的问题中,你有覆盖方法将Point2D
类打印到Point3D
类,这样做很好。
意味着您在Print
中专门实施了功能Point3D
,该功能与Point2D
的{{1}}功能完全相同,并且应打印有关3D点的信息。
但是你在Print
类中继承了Print
类的方法Drawing2D
,这意味着从Drawing3D
的对象调用Print
方法将执行方法Drawing3D
。
现在正在研究Drawring2D
的方法,您正在打印有关Drawing2D
类点的信息(Drawing2D
有自己的点列表,哪些点不同于Drawing2D
点的列表{ {1}}有)。
所以当您从Drwaing3D
调用Drwaing3D
方法时设置Print
点后,您正在调用Drawing3D
Print
方法,该方法会尝试打印关于它自己的点的信息(我们没有设置 - 因为我们设置了Drawing2D
)。
所以你可以做的是,
由于您拥有Drawing3D
类的过度使用方法,因此您还应该在Point
类中覆盖Print
类的Drawing2D
方法。
如下所示。
Drwaing3D
此处class Drawing2D
{
public string Name { get; set; }
public virtual List<IPoint> Points { get; set; }
public Drawing2D(string name)
{
Name = name;
Points = new List<IPoint>();
}
public virtual void Print()
{
Console.WriteLine("Drawing name: {"+Name+"}");
foreach (var point in Points)
point.Print();
}
}
class Drawing3D : Drawing2D
{
public new List<IPoint> Points { get; set; }
public Drawing3D(string name) : base(name)
{
Points = new List<IPoint>();
}
public override void Print()
{
Console.WriteLine("Drawing name: {"+Name+"}");
foreach (var point in Points)
point.Print();
}
}
是IPoint
类应实现的接口。
Point
UPDATE (这将是继承而不是覆盖)
但是高级代码可以正常工作。但我并不认为它完美无瑕。
第一点:点总是1维,所以不应该有2D点或3D点。
相反,只能绘制2D或3D(这里基于它的点数)。
另外,在两个绘图类中,我们都有耦合的打印信息代码。这是重复的,我们可以将它们放在一个地方。
我建议改变代码如下。
单点类(此处不需要多重实现或继承)
public interface IPoint
{
void Print();
}
class Point2D : IPoint
{
public int X { get; set; }
public int Y { get; set; }
public Point2D(int x, int y)
{
X = x;
Y = y;
}
public virtual void Print()
{
Console.WriteLine("2D Point: [{"+X+"}, {"+Y+"}]");
}
}
class Point3D:Point2D, IPoint
{
public int Z { get; set; }
public Point3D(int x, int y, int z):base(x,y)
{
Z = z;
}
public override void Print()
{
Console.WriteLine("3D Point: [{"+X+"}, {"+Y+"}, {"+Z+"}]");
}
}
基础绘图类,它具有打印功能和其他常用属性,如点列表和名称(这将是2D或3D类的常见)。
class Point
{
public int Val { get; set; }
public string CordinateName {get; set;}
public Point(int val, string cordinateName)
{
Val = val;
CordinateName = cordinateName;
}
public virtual void Print()
{
Console.WriteLine(CordinateName + " Point: [{"+Val+"}]");
}
}
从Drawing中得到的2D绘图非常清楚。
class Drawing
{
public List<Point> Points { get; set; }
public string Name {get; set;}
public Drawing(string name)
{
Name = name;
Points = new List<Point>();
}
public void Print()
{
Console.WriteLine("Drawing name: {"+Name+"} ");
foreach (var point in Points)
point.Print();
}
}
3D绘图源自2D绘图,因为3D绘图保存了2D绘图的所有特征(此处为X和Y点以及Drawing类的继承特征),还有一些专用于3D绘图的其他特征(第3点)。 / p>
class Drawing2D : Drawing
{
public Drawing2D(string name, int xPoint, int yPoint) : base (name)
{
Points.Add(new Point(xPoint, "X"));
Points.Add(new Point(yPoint, "Y"));
}
}
最后是你的呼叫机制。
class Drawing3D : Drawing2D
{
public Drawing3D(string name, int xPoint, int yPoint, int zPoint) : base(name, xPoint, yPoint)
{
Points.Add(new Point(zPoint, "Z"));
}
}
答案 2 :(得分:0)
让Point2D
和Point3D
实现相同的界面,让我们说IPoint
。然后在这两个类中,您可以创建IPoint
类型的字段。然后,您可以保留对两种类型对象的引用:Point2D
和Point3D
。
这是一般规则:
Porgram接口,而不是实现。
完全适用于此。这只是设计原则中的一个,您可能需要阅读它。
在界面中,您将实现方法Print()
(将在具体类中正确实现),绘图类中的方法Print()
应该将任务委派给IPoint.Print()
。
以下是根据我的评论重构的代码:
public interface IPoint
{
void Print();
}
class Point2D : IPoint
{
public int X { get; set; }
public int Y { get; set; }
public Point2D(int x, int y)
{
X = x;
Y = y;
}
public void Print()
{
Console.WriteLine($"2D Point: [{X}, {Y}]");
}
}
class Point3D : IPoint
{
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
public Point3D(int x, int y, int z)
{
X = x;
Y = y;
Z = z;
}
public void Print()
{
Console.WriteLine($"3D Point: [{X}, {Y}, {Z}]");
}
}
class Drawing2D
{
public string Name { get; set; }
public List<IPoint> Points { get; set; }
public Drawing2D(string name)
{
Name = name;
Points = new List<IPoint>();
}
public void Print()
{
Console.WriteLine($"Drawing name: {Name}");
foreach (var point in Points)
point.Print();
}
}
class Drawing3D : Drawing2D
{
public Drawing3D(string name) : base(name) { }
}