Graphics 在面向对象设计方面,二维和三维点类可以从单个基类派生吗?

Graphics 在面向对象设计方面,二维和三维点类可以从单个基类派生吗?,graphics,oop,Graphics,Oop,我目前正在设计simple graphic editor,它支持二维和三维形状的琐碎操作。 关键是,我想像MsPaint一样渲染这些形状的原型。在渲染的时候,我需要将画布上的像素存储在原型所覆盖的地方,以防原型更改以恢复画布上的状态。因此,我希望我的所有形状都支持这种缓冲(图形操作是所有渲染操作的基类): 公共抽象类形状:GraphicOperation{ 保护列表备份; 公共形状(颜色c):基(c){} 公共颜色图形颜色{ 获取{返回颜色;} 受保护集{color=value;} } 公共抽象

我目前正在设计simple graphic editor,它支持二维和三维形状的琐碎操作。
关键是,我想像MsPaint一样渲染这些形状的原型。在渲染的时候,我需要将画布上的像素存储在原型所覆盖的地方,以防原型更改以恢复画布上的状态。因此,我希望我的所有形状都支持这种缓冲(图形操作是所有渲染操作的基类):

公共抽象类形状:GraphicOperation{
保护列表备份;
公共形状(颜色c):基(c){}
公共颜色图形颜色{
获取{返回颜色;}
受保护集{color=value;}
}
公共抽象void renderPrototype(位图canvasToDrawOn);
}

其主要思想是,就OO设计而言,最好在基类(形状)级别提供缓冲区支持,我的意思是,对于TwoDShape和ThreeDShape类,此列表必须以不同的方式初始化-对于TwoDShape和TwoDPoint实例,以及对于ThreeDShape和ThreeDPoint实例。
但要做到这一点,SomePoint必须是二维点类和三维点类的基类。就OO而言,从单个基类派生这两个类可以接受吗?
可能有太多的话,但我只是想让每个人都明白这个问题。
编辑:顺便问一句,从他们的形状之王中派生点类是个好主意吗?我个人认为没有其他选择,但如果我直接从形状推导出来,可能会更好?现在是:

public abstract class TwoDShape : Shape {
        protected List<SomePoint> backup;
        public TwoDShape(Color c) : base(c) { }
    }
public class TwoDPoint: TwoDShape {
        //...
}
公共抽象类TwoDShape:Shape{
保护列表备份;
公共TwoDShape(颜色c):基(c){}
}
公共类TwoDPoint:TwoDShape{
//...
}

三点也是一样。

在游戏中,2d点和3d点通常不会相互继承,但老实说,我想不出任何根本原因。所以,是的,它应该是好的,至于命名,它们通常是vector2和vector3,所以它们可以容纳尺寸、点和颜色,都在同一个对象中。

我看不出有任何理由不这样做。但是,如果形状之间的唯一区别在于它们所包含的点的类型,为什么不让形状类本身成为一个模板,或者Java术语中的“泛型”呢?

难道不能让三维点从二维点派生出来吗

public class ThreeDimensionalPoint : TwoDimensionalPoint
{

}

我可以在2D中看到很多可重用的代码(方法/属性),而在3D中也一样。。。你可能想从2d的角度看3D,然后你所需要做的就是投射它。只是我的想法…

二维点和三维点到底有什么共同点?如果只是“在将它们绘制到曲面上时,它们会替换应该备份的像素”,那么对我来说,这听起来更像是合成而不是继承。2d和3d形状都有一个像素缓冲区,用于替换像素

无论如何,当需要基类时,您是否可以始终同时使用2d和3d形状

如果是这样,给他们一个公共基类。否则不要


基于对象的使用方式进行类设计。如果它们在具有公共基类的上下文中使用,则将其实现为公共基类。如果只是“我不想为两者都添加一个数据成员而烦恼”,那么继承可能不是正确的工具。

OOD有一条完全通用的规则,即:支持组合而不是继承

这在实践中意味着不应该使用继承进行代码重用。如果使用继承的动机是利用多态性,那么使用继承仍然是合法和有效的

在您的情况下,如果您能够设法在某种程度上编写抽象类/接口,这样您就只能在该级别上处理它,并且永远不需要向下转换,那么您肯定应该这样做


另一方面,如果您发现需要将实例向下转换为(比如)两个点或三个点,那么您从继承中什么也得不到,您将违反Liskov替换原则。如果是这样的话,你应该考虑一个设计,你可以在不使用继承的情况下实现重用——也许是使用服务或策略。

< P>我想不出有什么办法来做到这一点,这并不违反LISKOV替代原则的一些微妙(或不那么微妙)的方式。这是一个典型的例子,说明为什么不疯狂使用继承,仅仅因为两个类共享一些字段,例如or


最后,即使你让它工作,它可能会有这么多的陷阱和限制,你写的方法,我无法想象这将是一个净胜利。

一个简单的解决方案,并将避免一些微妙的设计问题是,只要把所有点视为三维和简单地忽略Z坐标,如果你是在二维环境中工作。你可以考虑一个2D形状仅仅是一个3D形状,它恰巧位于平面上。

HM,我想不出两个之间可以重用的东西。想详细说明一下吗?三维形状不是二维形状。它可以投影到二维平面上,但它不是二维形状。我可以,但这不是一个可重用的决定,最重要的是我必须把这个列表和恢复的点放在层次结构的一个层次上-所以它不是那么灵活eitherjalf-我同意,就OO而言,从另一个点派生并不是更好的主意2d点x,y,3d点x,y,z我不知道我肯定不是一个图形/游戏专家…我同意jalf。如果有的话,二维点应该继承自三维点,因为二维点是三维点。好的子类通常会约束基类所表示的概念,而不是扩展它(例如,方形继承自矩形继承自多边形继承自形状)。但我所有的形状(包括两个点类)都是从形状派生的,因此它们将
public class ThreeDimensionalPoint : TwoDimensionalPoint
{

}