简体   繁体   中英

C# Method arguments and Subclass Types

I started to learn C# but I am confused about something. Let's say I have a class and 2 subclasses. I have a method inside the parent class called Add(). But when I use this method with subclasses, since the method is asking for a "Toople" and not a "Vector" or a "Point", it gives me an error. How can I solve this issue? Is there a way to allow subclasses to be inserted into the method or should I create new methods for each different subclass? Thanks a lot.

using System;
namespace RayTracerChallange
{
    public class Toople
    {
        public float x, y, z, w;

        public Toople(float X, float Y, float Z, float W)
        {
            x = X;
            y = Y;
            z = Z;
            w = W;

        }
        public Toople Add(Toople Toop)
        {
            return new Toople(this.x + Toop.x, this.y + Toop.y, this.z + Toop.z, this.w + Toop.w);
        }

  public class Point : Toople
  {
      Point(float X, float Y, float Z) : base(X, Y, Z, 1)
      {
          this.x = X;
          this.y = Y;
          this.z = Z;
      }
  }

  public class Vector : Toople
  {
      Vector(float X, float Y, float Z) : base(X, Y, Z, 0)
      {
          this.x = X;
          this.y = Y;
          this.z = Z;
      }
  }

The closest you're going to get here is by making Toople generic and abstract, possibly by doing something like this:

using System;
namespace RayTracerChallange
{
    public abstract class ToopleBase<T> where T : ToopleBase<T>
    {
        public float x, y, z, w;

        protected Toople(float X, float Y, float Z, float W)
        {
            x = X;
            y = Y;
            z = Z;
            w = W;

        }
        protected abstract T MakeT(float X, float Y, float Z, float W);

        public T Add(Toople Toop)
        {
            return makeT(this.x + Toop.x, this.y + Toop.y, this.z + Toop.z, this.w + Toop.w);
        }
  }

  public class Toople : ToopleBase<Toople>
  {
      Toople(float X, float Y, float Z, float W) : base(X, Y, Z, W)
      {
      }

      Toople MakeT(float X, float Y, float Z, float W)
      {
          return new Toople(X, Y, Z, W);
      }
  }

  public class Point : ToopleBase<Point>
  {
      Point(float X, float Y, float Z) : base(X, Y, Z, 1)
      {
      }

      protected override Point MakeT(float X, float Y, float Z, float W)
      {
          return new Point(X, Y, Z);
      }
  }

  public class Vector : ToopleBase<Vector>
  {
      Vector(float X, float Y, float Z) : base(X, Y, Z, 0)
      {
      }

      protected override Point MakeT(float X, float Y, float Z, float W)
      {
          return new Vector(X, Y, Z);
      }
  }

A couple things to note:

  • I'm not sure why you would want to do this, it should be good enough to simply return the base class Toople if you are following the Liskov Substitution Principle. (That is, the rest of the application should be able to expect any subclasses to behave in the same way as their base class, and should not even have the knowledge that the subclasses exist.)
  • The constructors of the child classes don't need to set the fields in the parent class, since the parent class is already doing that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM