C# 使用C中构建器的子类型“返回此”

C# 使用C中构建器的子类型“返回此”,c#,inheritance,builder,C#,Inheritance,Builder,我能让这个C代码做我想做的并且让ShapeBuilder.color返回这个的派生子类型吗 class Shape { public String Color { get; private set; } public Shape(String color) { this.Color = color; } } class Circle : Shape { public int Radius { get; private set; } pu

我能让这个C代码做我想做的并且让ShapeBuilder.color返回这个的派生子类型吗

class Shape {
    public String Color { get; private set; }

    public Shape(String color) {
        this.Color = color;
    }
}
class Circle : Shape {
    public int Radius { get; private set; }

    public Circle(String color, int radius) : base(color) {
        this.Radius = radius;
    }

    public override String ToString() {
        return String.Format("Circle c={0} r={1}", this.Color, this.Radius);
    }
}

class ShapeBuilder {
    // How can this function return the subtype, not just a ShapeBuilder?
    public ShapeBuilder color(String color) {
        this._color = color;
        return this;        
    }

    protected String _color;
}
class CircleBuilder : ShapeBuilder {
    public CircleBuilder radius(int radius) {
        this._radius = radius;
        return this;        
    }

    public Circle build() {
        return new Circle(_color, _radius);
    }

    protected int _radius;
}

class Program {
    static void Main() {
        // This works.
        Circle c1 = new CircleBuilder().radius(5).build();
        Console.WriteLine("c1: " + c1);

        // This won't compile, because color returns ShapeBuilder rather than CircleBuilder.
        Circle c2 = new CircleBuilder().color("blue").build();
        Console.WriteLine("c2: " + c2);
    }
}
在Scala中,我会这样做:

case class Shape(val color: String)
class Circle(color: String, radius: Int) extends Shape(color)

class ShapeBuilder {
  def color(color: String): this.type = {
    this.color = color
    this
  }

  def build() = new Shape(color)

  protected var color: String = ""
}

class CircleBuilder extends ShapeBuilder {
  def radius(radius: Int): this.type = {
    this.radius = radius
    this
  }

  override def build() = new Circle(color, radius)

  protected var radius: Int = 0
}

object BuilderTest extends App {
    val c = new CircleBuilder().color("blue").radius(5).build();
}
见:

也许你可以用泛型

ShapeBuilder<T>
见:

也许你可以用泛型

ShapeBuilder<T>

它可以通过泛型完成。Scala版本是最好的,因为它根本不需要泛型来提供this.type的派生类型。以下是C版本:

class Shape {
    public String Color { get; private set; }

    public Shape(String color) {
        this.Color = color;
    }

public override String ToString() {
        return String.Format("Shape c={0}", this.Color);
    }
}
class Circle : Shape {
    public int Radius { get; private set; }

    public Circle(String color, int radius) : base(color) {
        this.Radius = radius;
    }

    public override String ToString() {
        return String.Format("Circle c={0} r={1}", this.Color, this.Radius);
    }
}

interface Builder<T> {
    T build();
}
abstract class AbstractShapeBuilder<B, T> : Builder<T> where B : AbstractShapeBuilder<B, T> where T : Shape {
    abstract protected B getThis();

    abstract public T build();

    public B color(String color) {
        this._color = color;
        return getThis();        
    }

    protected String _color;
}
class ShapeBuilder : AbstractShapeBuilder<ShapeBuilder, Shape> {
    override protected ShapeBuilder getThis() { return this; }

    override public Shape build() {
        return new Shape(_color);
    }
}

abstract class AbstractCircleBuilder<B, T> : AbstractShapeBuilder<B, T> where B : AbstractCircleBuilder<B, T> where T : Circle {
    public B radius(int radius) {
        this._radius = radius;
        return getThis();        
    }

    protected int _radius;
}
class CircleBuilder : AbstractCircleBuilder<CircleBuilder, Circle> {
    override protected CircleBuilder getThis() { return this; }

    override public Circle build() {
        return new Circle(_color, _radius);
    }
}

class Program {
    static void Main() {
        Console.WriteLine("CircleBuilder: v1");

        Shape s1 = new ShapeBuilder().color("yellow").build();
        Console.WriteLine("s1: " + s1);

        Circle c1 = new CircleBuilder().color("blue").radius(3).build();
        Console.WriteLine("c1: " + c1);
    }
}
仅供参考,以下是Java版本:

public class BuilderTest {
    public static class Shape {
        public Shape(String color) {
            this.color = color;
        }

        @Override public String toString() {
            return String.format("shape. color=%s.", color);
        }

        public final String color;
    }
    public static class Circle extends Shape {
        public Circle(String color, int radius) {
            super(color);
            this.radius = radius;
        }

        @Override public String toString() {
            return String.format("circle. color=%s. radius=%d.", color, radius);
        }

        public final int radius;
    }

    @FunctionalInterface
    public static interface Builder<T> {
        public T build();
    }

    public static abstract class AbstractShapeBuilder<B extends AbstractShapeBuilder<B>> {
        protected abstract B getDerivedThis();

        public B color(String color) {
            this.color = color;
            return getDerivedThis();
        }

        String color;
    }
    public static class ShapeBuilder extends AbstractShapeBuilder<ShapeBuilder> implements Builder<Shape> {
        @Override protected ShapeBuilder getDerivedThis() { return this; }

        @Override public Shape build() {
            return new Shape(color);
        }
    }

    public static abstract class AbstractCircleBuilder<B extends AbstractCircleBuilder<B>> extends AbstractShapeBuilder<B> {
        public B radius(int radius) {
            this.radius = radius;
            return getDerivedThis();
        }

        int radius;
    }
    public static class CircleBuilder extends AbstractCircleBuilder<CircleBuilder> implements Builder<Circle> {
        @Override protected CircleBuilder getDerivedThis() { return this; }

        @Override public Circle build() { return new Circle(color, radius); }
    }

    public static void main(String[] args) throws Exception {
        Shape s = new ShapeBuilder().color("red").build();
        System.out.println("s = " + s);

        Circle c = new CircleBuilder().color("blue").radius(5).build();
        System.out.println("c = " + c);
    }
}

它可以通过泛型完成。Scala版本是最好的,因为它根本不需要泛型来提供this.type的派生类型。以下是C版本:

class Shape {
    public String Color { get; private set; }

    public Shape(String color) {
        this.Color = color;
    }

public override String ToString() {
        return String.Format("Shape c={0}", this.Color);
    }
}
class Circle : Shape {
    public int Radius { get; private set; }

    public Circle(String color, int radius) : base(color) {
        this.Radius = radius;
    }

    public override String ToString() {
        return String.Format("Circle c={0} r={1}", this.Color, this.Radius);
    }
}

interface Builder<T> {
    T build();
}
abstract class AbstractShapeBuilder<B, T> : Builder<T> where B : AbstractShapeBuilder<B, T> where T : Shape {
    abstract protected B getThis();

    abstract public T build();

    public B color(String color) {
        this._color = color;
        return getThis();        
    }

    protected String _color;
}
class ShapeBuilder : AbstractShapeBuilder<ShapeBuilder, Shape> {
    override protected ShapeBuilder getThis() { return this; }

    override public Shape build() {
        return new Shape(_color);
    }
}

abstract class AbstractCircleBuilder<B, T> : AbstractShapeBuilder<B, T> where B : AbstractCircleBuilder<B, T> where T : Circle {
    public B radius(int radius) {
        this._radius = radius;
        return getThis();        
    }

    protected int _radius;
}
class CircleBuilder : AbstractCircleBuilder<CircleBuilder, Circle> {
    override protected CircleBuilder getThis() { return this; }

    override public Circle build() {
        return new Circle(_color, _radius);
    }
}

class Program {
    static void Main() {
        Console.WriteLine("CircleBuilder: v1");

        Shape s1 = new ShapeBuilder().color("yellow").build();
        Console.WriteLine("s1: " + s1);

        Circle c1 = new CircleBuilder().color("blue").radius(3).build();
        Console.WriteLine("c1: " + c1);
    }
}
仅供参考,以下是Java版本:

public class BuilderTest {
    public static class Shape {
        public Shape(String color) {
            this.color = color;
        }

        @Override public String toString() {
            return String.format("shape. color=%s.", color);
        }

        public final String color;
    }
    public static class Circle extends Shape {
        public Circle(String color, int radius) {
            super(color);
            this.radius = radius;
        }

        @Override public String toString() {
            return String.format("circle. color=%s. radius=%d.", color, radius);
        }

        public final int radius;
    }

    @FunctionalInterface
    public static interface Builder<T> {
        public T build();
    }

    public static abstract class AbstractShapeBuilder<B extends AbstractShapeBuilder<B>> {
        protected abstract B getDerivedThis();

        public B color(String color) {
            this.color = color;
            return getDerivedThis();
        }

        String color;
    }
    public static class ShapeBuilder extends AbstractShapeBuilder<ShapeBuilder> implements Builder<Shape> {
        @Override protected ShapeBuilder getDerivedThis() { return this; }

        @Override public Shape build() {
            return new Shape(color);
        }
    }

    public static abstract class AbstractCircleBuilder<B extends AbstractCircleBuilder<B>> extends AbstractShapeBuilder<B> {
        public B radius(int radius) {
            this.radius = radius;
            return getDerivedThis();
        }

        int radius;
    }
    public static class CircleBuilder extends AbstractCircleBuilder<CircleBuilder> implements Builder<Circle> {
        @Override protected CircleBuilder getDerivedThis() { return this; }

        @Override public Circle build() { return new Circle(color, radius); }
    }

    public static void main(String[] args) throws Exception {
        Shape s = new ShapeBuilder().color("red").build();
        System.out.println("s = " + s);

        Circle c = new CircleBuilder().color("blue").radius(5).build();
        System.out.println("c = " + c);
    }
}

最简单、最惯用的方法就是使用新方法

为什么这是一个好方法

在这种情况下,泛型是不好的,因为它们使编写在不同ShapeBuilder上进行多态操作的代码变得更加复杂。像这样的泛型基类倾向于强制调用代码也是泛型的,没有什么好处

ShapeBuilder s=新的CircleBuilder;s、 彩色的;比AbstractShapeBuilder s=new CircleBuilder更易于使用和作为参数传递;s、 彩色的

像这样使用new关键字可以让子类型的用户获得了解特定类型的好处,还可以让超类型的用户进行多态操作,而不会给调用者带来任何额外的复杂性。这种技术在.NET Framework中随处可见,你甚至没有注意到它,因为它非常直观-这就是如何实现相同的基本方法,即使它们有不同的返回类型


但我觉得通用版本更难看,可读性更低,使用更复杂。

最简单、最惯用的方法是使用新方法

为什么这是一个好方法

在这种情况下,泛型是不好的,因为它们使编写在不同ShapeBuilder上进行多态操作的代码变得更加复杂。像这样的泛型基类倾向于强制调用代码也是泛型的,没有什么好处

ShapeBuilder s=新的CircleBuilder;s、 彩色的;比AbstractShapeBuilder s=new CircleBuilder更易于使用和作为参数传递;s、 彩色的

像这样使用new关键字可以让子类型的用户获得了解特定类型的好处,还可以让超类型的用户进行多态操作,而不会给调用者带来任何额外的复杂性。这种技术在.NET Framework中随处可见,你甚至没有注意到它,因为它非常直观-这就是如何实现相同的基本方法,即使它们有不同的返回类型


但我觉得通用版本更难看,可读性更低,使用起来也更复杂。

我在发布这篇文章之前读过这个链接。这基本上是说不,在C语言中没有干净的方法可以做到这一点。我在发布这篇文章之前阅读了这个链接。这基本上是否定的,在C中没有明确的方法来实现这一点。这仍然不会编译:Circle c2=new CircleBuilder.colorblue.radius3.build;这仍然无法编译:Circle c2=new CircleBuilder.colorblue.radius3.build;很不错的。C代码简介:不需要getThis方法;只需使用生成器类型参数B->返回B this来强制转换它;该强制转换不能保证安全。Java编译器将对该强制转换发出警告,Mono C编译器不会发出警告,但它应该发出警告。泛型约束是否明确保证了安全性,因为它强制执行的B类型参数与自身的类型相同?你能提供一个抛出InvalidCastException的例子吗?我复制了上面的C,删除了getThis,更改了使用强制转换的返回,并且我可以添加这个类,该类在运行时编译并成功触发InvalidCastException:类ShapeBuilder2:AbstractShapeBuilder{override public Shape build{返回新形状\颜色;}}谢谢你的示例非常好。C代码的简要说明:getThis方法是不需要的;只需使用生成器类型参数B->return B this强制转换此方法;该强制转换不能保证编译器的安全。Java编译器将在该强制转换上发出警告,Mono C编译器不会发出警告,但它应该发出警告。泛型约束不是明确的吗请确保安全,因为它强制执行的B类型参数与它本身的类型相同?您能提供一个抛出InvalidCastException的示例吗?我复制了上面的C,删除了getThis,更改了返回以使用强制转换,并且我可以添加这个类,该类在运行时编译并成功触发InvalidCastException:class ShapeBuilder2:AbstractShapeBuilder{覆盖公共形状构建{返回新形状\u颜色;}}}感谢您的示例