RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 570778
Accepted
Anton Tregubenkov
Anton Tregubenkov
Asked:2020-09-27 13:42:31 +0000 UTC2020-09-27 13:42:31 +0000 UTC 2020-09-27 13:42:31 +0000 UTC

如何使 3 个构造函数具有相同的签名?

  • 772

我们需要编写一个包含该类的程序Triangle。这个类应该有三个构造函数:

  1. 接受三个边的构造函数。
  2. 一个构造函数,它取两条边和它们之间的角度,并使用余弦定理计算第三条边。
  3. 一个构造函数,它取两个角和它们之间的一条边,并使用正弦定理(记住三角形角和定理)计算剩余的边。

每个Triangle人还必须返回自己的区域。

也就是说,我们有以下内容:

class Triangle
{
    Triangle(double side1, double side2, double side3)
    {
    }
    Triangle(double side1, double side2, double angle)
    {
    }
    Triangle(double side1, double angle1, double angle2)
    {
    }
}

整个问题是所有三个构造函数都具有相同的签名,但逻辑不同。
问题:如何“正确”解决这个问题?

“错误”选项:

  1. 用 替换参数并 double进一步string解析string。double
  2. double用替换参数float。
  3. 将参数传输到数组:

    Triangle(double[] sides, double angle)
    
  4. 创建新的数据类型Angle。
c#
  • 4 4 个回答
  • 10 Views

4 个回答

  • Voted
  1. Best Answer
    Pavel Mayorov
    2020-09-27T13:55:22Z2020-09-27T13:55:22Z

    选项 1 - 使用命名构造函数。

    命名构造函数是一种静态方法,其任务是创建具有给定参数的对象。有时它们仍不能完全正确地称为工厂方法。

    class Triangle
    {
        private Triangle() {}
    
        public static Triangle From3Sides(double side1, double side2, double side3) { ... }
    
        public static Triangle From2SidesAndAngle(double side1, double side2, double angle) { ... }
    
        public static Triangle FromSideAnd2Angles(double side, double angle1, double angle2) { ... }
    }
    

    选项 2 - 使用域数据类型

    我们定义数据类型“长度”和“角度”——并在构造函数中使用它们。

    class Length
    {
      public double Value { get; }
    
      public Length() {}
      public Length(double value) { Value = value; }
    
      public static implicit operator double (Length length)
        => length.Value;
      public static implicit operator Length (double value)
        => new Length(value);
    }
    
    class Angle
    {
      public double Value { get; }
    
      public Angle() {}
      public Angle(double value) { Value = value; }
    
      public static implicit operator double (Angle angle)
        => angle.Value;
      public static implicit operator Angle (double value)
        => new Angle(value);
    }
    
    • 18
  2. Argon
    2020-09-27T18:38:06Z2020-09-27T18:38:06Z

    作为一个选项,将参数集分组为结构:

    public struct ThreeSides
    {
        double side1;
        double side2;
        double side3;
    }
    public struct TwoSidesAndAngle
    {
        double side1;
        double side2;
        double angle;
    }
    public struct SideAndTwoAngles
    {
        double side1;
        double angle1;
        double angle2;
    }
    
    public class Triangle
    {
        public Triangle(ThreeSides params)
        {
        }
    
        public Triangle(TwoSidesAndAngle params)
        {
        }
    
        public Triangle(SideAndTwoAngles params)
        {
        }
    }
    

    但在我看来,Pavel 的回答是工厂更正确的选择

    • 4
  3. αλεχολυτ
    2020-09-27T19:31:50Z2020-09-27T19:31:50Z

    已经建议的几个替代方案。

    因为 重载函数(包括构造函数)的选择是基于类型的,显然创建多个具有相同签名的不同构造函数是行不通的。

    这个问题可以通过添加一个额外的参数来解决。

    1. 创建了新的“空”类(名称取自@Argon 的回答):

      class ThreeSides {}
      class TwoSidesAndAngle {}
      class SideAndTwoAngles {} 
      

      这种情况下的构造函数签名如下:

      Triangle(double side1, double side2, double side3, ThreeSides unused);
      Triangle(double side1, double side2, double angle, TwoSidesAndAngle unused);
      Triangle(double side1, double angle1, double angle2, SideAndTwoAngles unused);
      
    2. 使用枚举enum。

      enum Kind { ThreeSides, TwoSidesAndAngle, SideAndTwoAngles }
      

      在这种情况下,构造函数将是唯一一个内部有逻辑分支的构造函数:

      Triangle(double arg1, double arg2, double arg3, Kind kind);
      

      在这种情况下,kind如果计划采用一种或另一种构建三角形的变体,则可以将参数设置为默认值。例如:

      Triangle(double arg1, double arg2, double arg3, Kind kind = Kind.ThreeSides);
      
    • 1
  4. Qwertiy
    2020-11-21T18:56:26Z2020-11-21T18:56:26Z

    如果你愿意,你可以这样做:

    http://ideone.com/XLf5Pz

    using System;
    
    class Triangle
    {
        public struct NeverCreateMe {}
    
        public Triangle(double side1, double side2, double side3)
        {
            Console.WriteLine("3 sides");
        }
    
        public Triangle(double side1, double side2, NeverCreateMe ignored = default(NeverCreateMe), double angle = 0)
        {
            Console.WriteLine("2 sides and 1 angle");
        }
    
        public Triangle(double side1, NeverCreateMe ignored = default(NeverCreateMe), double angle1 = 0, double angle2 = 0)
        {
            Console.WriteLine("1 side and 2 angles");
        }
    }
    
    public class Test
    {
        public static void Main()
        {
            var a = new Triangle(1.0, 2.0, 3.0);
            var b = new Triangle(1.0, 2.0, angle: 3.0);
            var c = new Triangle(1.0, angle1: 2.0, angle2: 3.0);
        }
    }
    

    甚至这样:

    http://ideone.com/VEGn2s

    using System;
    
    class Triangle
    {
        public struct NeverCreateMe<T> {}
    
        public Triangle(double side1, double side2, double side3)
        {
            Console.WriteLine("3 sides");
        }
    
        public Triangle(double side1, double side2, double angle, NeverCreateMe<bool> ignored = default(NeverCreateMe<bool>))
        {
            Console.WriteLine("2 sides and 1 angle");
        }
    
        public Triangle(double side1, double angle1, double angle2, NeverCreateMe<int> ignored = default(NeverCreateMe<int>))
        {
            Console.WriteLine("1 side and 2 angles");
        }
    }
    
    public class Test
    {
        public static void Main()
        {
            var a = new Triangle(1.0, 2.0, 3.0);
            var b = new Triangle(1.0, 2.0, angle: 3.0);
            var c = new Triangle(1.0, angle1: 2.0, angle2: 3.0);
        }
    }
    

    每种方法都有其优点和缺点,但如果需要,可以解决它们。

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何停止编写糟糕的代码?

    • 3 个回答
  • Marko Smith

    onCreateView 方法重构

    • 1 个回答
  • Marko Smith

    通用还是非通用

    • 2 个回答
  • Marko Smith

    如何访问 jQuery 中的列

    • 1 个回答
  • Marko Smith

    *.tga 文件的组重命名(3620 个)

    • 1 个回答
  • Marko Smith

    内存分配列表C#

    • 1 个回答
  • Marko Smith

    常规赛适度贪婪

    • 1 个回答
  • Marko Smith

    如何制作自己的自动完成/自动更正?

    • 1 个回答
  • Marko Smith

    选择斐波那契数列

    • 2 个回答
  • Marko Smith

    所有 API 版本中的通用权限代码

    • 2 个回答
  • Martin Hope
    jfs *(星号)和 ** 双星号在 Python 中是什么意思? 2020-11-23 05:07:40 +0000 UTC
  • Martin Hope
    hwak 哪个孩子调用了父母的静态方法?还是不可能完成的任务? 2020-11-18 16:30:55 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    Arch ArrayList 与 LinkedList 的区别? 2020-09-20 02:42:49 +0000 UTC
  • Martin Hope
    iluxa1810 哪个更正确使用:if () 或 try-catch? 2020-08-23 18:56:13 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5