首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >派生不同类型的封装类

派生不同类型的封装类
EN

Stack Overflow用户
提问于 2018-06-16 05:36:42
回答 3查看 240关注 0票数 2

我想重写一个具有不同类型的属性。

假设我有一个类Point3D,它继承了Point2D,而Class Drawing3D继承了Drawing2D

我希望两个类Drawing2D和Drawing3D都有相同的属性名点,这将是Drawing2D的Point2D列表,Drawing3D的Point3D列表。

使用相同的属性名,我希望Drawing3D能够在属性点上使用Drawing2D方法。问题是我不能使用重写,因为类型不同。关键字不起作用,因为Drawing3D似乎有两个属性点( Point2D列表和Point3D列表)。使用Drawing3D上的基本方法,它将遍历Point2D列表。

我的2D课程:

代码语言:javascript
复制
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类

代码语言:javascript
复制
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>();
    }
}

还有我的主程序

代码语言:javascript
复制
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。

希望你们能帮我。我喜欢有优雅的代码,也许我的方法不是正确的.

干杯

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-06-16 05:55:07

Point2DPoint3D实现相同的接口,比如IPoint。然后,在这两个类中,您可以创建IPoint类型的字段。然后,您可以保留对两种对象类型的引用:Point2DPoint3D

这是一般规则:

端口到接口,而不是到实现。

这完全适用于这里。这只是设计原则中的一个,您可能想了解一下。

在接口中,您将实现方法Print() (它将在具体的类中适当地实现),来自绘图类的方法Print()应该将任务委托给IPoint.Print()

下面是对我的评论进行重构的代码:

代码语言:javascript
复制
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) { }
}
票数 0
EN

Stack Overflow用户

发布于 2018-06-16 06:13:29

如果你必须做上面的例子,那么你可以这样做。

代码语言:javascript
复制
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;
        }
    }
票数 2
EN

Stack Overflow用户

发布于 2018-06-16 06:25:30

在您的问题中,您已经将Point2D类的方法打印覆盖到Point3D类中,这很好。

这意味着您已经在Point3D中专门实现了功能Point3D,它与Point2DPrint功能分离,应该打印有关3D点的信息。

但是,您在Print类中继承了Drawing2D类的方法Drawing3D,这意味着Drawing3D对象对Print方法的任何调用都将执行Drawring2D方法。

现在来看一下Drawing2D的方法,您正在打印关于Drawing2D类的点的信息(Drawing2D有自己的点列表,与Drwaing3D的点列表不同)。

因此,在从Drwaing3D中调用Print方法之后,您将调用Drawing2DPrint方法,并且该方法将尝试打印有关它自己的点的信息(我们还没有设置--因为我们已经设置了Drawing3D的点)。

所以你能做的就是

由于您已经重写了Point类的方法,所以还应该在Drwaing3D类中重写Drawing2D类的Print方法。

就像下面。

代码语言:javascript
复制
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类应该实现的接口。

代码语言:javascript
复制
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点。

相反,绘图只能是2D或3D (这里根据它所拥有的点数)。

另外,在两个绘图类中,我们都有耦合的打印信息代码。这是重复的,我们可以把它们放在一个地方。

我提议进行如下代码更改。

单点类(这里不需要多个实现或继承)

代码语言:javascript
复制
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+"}]");
    }
}

一个基图类,它包含打印和其他公共属性的功能,如Point list和name (这将在2D或3D类中都是常见的)。

代码语言:javascript
复制
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();
    } 
}

从绘图中派生出来的2D绘图几乎是被理解的。

代码语言:javascript
复制
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"));
    }
}

3D绘图源于二维绘图,因为3D绘图包含了二维绘图的所有特征(这里是X点和Y点,以及继承的绘图类特征),同时也有一些其他特性(第3点)只用于3D绘图。

代码语言:javascript
复制
class Drawing3D : Drawing2D
{
    public Drawing3D(string name, int xPoint, int yPoint, int zPoint) : base(name, xPoint, yPoint)
    {
       Points.Add(new Point(zPoint, "Z"));
    }
}

最后是你的呼叫机制。

代码语言:javascript
复制
public class Program
{
    public static void Main(string[] args)
    {
        Drawing myDrawing3D = new Drawing3D("Sketch 3D", 10, 12, 14);
        myDrawing3D.Print();

        Drawing myDrawing2D = new Drawing2D("Sketch 2D", 10, 12);
        myDrawing2D.Print();

        Console.WriteLine("Done");
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50885274

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档