C#OOP继承类结构 [英] C# OOP inheritance class structure

查看:72
本文介绍了C#OOP继承类结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,



我正在开发的应用程序可以监督网络中的一些服务器,因为我正在学习OOP以完全正确的方式我在代码下实现。目标来自Program类,我将调用Heartbeatsupervisor类(引擎类),它将在Server类和Protocol类的construcot中获取2个参数,然后在Heartbeatsupervisor中的StartCheck方法中做一些工作。如果这是正确的方式,或者在OOP情况下可以更改某些内容,请你如此友好地检查并给我你的反馈。你怎么看?我试图处理更多受保护的属性,但由于访问而丢失。首先请检查并给出您的意见。问候。



基类Cocpit:

hi all,

I am developing application which would be abble to supervise some servers inside network as i am learning OOP to be fully correct way i implemented below code. The target is from Program class i will call Heartbeatsupervisor class (engine class) that would take 2 parameters inside construcot of Server class and Protocol class and then do some work in StartCheck method inside Heartbeatsupervisor as well. Could you please be so kind check and give me your feedback if this is correct way created or something could be changed in case OOP. Whats your opinion? I tried to deal with more protected properties but i lose due to access. Firstly please check and give your opinion. Regards.

Base class Cocpit:

public abstract class Cocpit: ICheck
    {

        protected string _id;
        protected string _name;

        public Cocpit()
        {
        }

        public Cocpit(string name)
        {
            Console.WriteLine("Default constructor of Cocpit called");
        }

        protected internal abstract string Id { get; set; }
        protected internal abstract string Name { get; set; }

        #region ICheck Members

        public virtual void StartCheck()
        {
            Console.WriteLine("Start check");
        }

        public virtual void StopCheck()
        {
            Console.WriteLine("Stop Check");
        }

        public virtual Dictionary<string, string> GetDictionary()
        {   
            return null;
        }

        #endregion

    }





从Cocpit派生的服务器类:



Server class derived from Cocpit:

public class Server: Cocpit
    {

        private string _ip;             //new field
        private Dictionary<string, string> _serverList;

        public Server(string name, string ip)
            : base(name)
        {
            this._ip = ip;
            this.Name = name;
            Console.WriteLine("Server default constructor called");
        }

        protected internal override string Id      
        {
            get { return _id; }
            set { _id = value; }
        }        //overriding property

        protected internal override string Name    
        {
            get { return _name; }
            set { _name = value; }
        }        //overriding property

        protected internal virtual string Ip               
        {
            get { return _ip; }
            set { _ip = value; }
        }        //new property

        #region Methods
        public Dictionary<string, string> ServerList
        {
            get { return _serverList; }
            private set { _serverList = value; }
        }

        #endregion

        #region Destructor
        
        /// <summary>
        /// Desctructor
        /// </summary>
        ~Server()
        {
        }

        #endregion

        #region Overrided Methods

        public override void StartCheck()
        {
            base.StartCheck();
            Console.WriteLine("StartCheck overrided");

            //TODO: [StartCheck] Check engine to be deployed
        }

        public override void StopCheck()
        {
            base.StopCheck();
            Console.WriteLine("StopCheck overrided");

            //TODO: [StopCheck] Check engine to be deployed
        }





派生自Cocpit的协议类:




Protocol class derived from Cocpit:

public class Protocol: Cocpit
  {

      /// This constructor will call Cocpit.Cocpit()
      public Protocol(string name)
          : base(name)
      {
      }

      protected internal override string Id
      {
          get { return _id;}
          set{_id = value;}
      }        //overriding property

      protected internal override string Name
      {
          get { return _name; }
          set { _name = value; }
      }        //overriding property

      #region Methods

      void EnumerateLists(IList list)
      {
          //notice that the list is passed an IList and hence can handle both types of lists
          //Use IEnumerable
          foreach (object val in list)
          {

          }
      }

      #endregion

  }





< u> Heartbeatsupervisor类(我的引擎):



Heartbeatsupervisor class (my engine):

public class HeartbeatSupervisor : ICheck
{

    private string _serverIp;
    private string _protocolName;

    public string ServerIp
    {
        get { return _serverIp; }
        set { _serverIp = value; }
    }

    public string ProtocolName
    {
        get { return _protocolName; }
        set { _protocolName = value; }
    }

    public HeartbeatSupervisor(Server server, Protocol protocol)
    {
        this._serverIp = server.Ip;
        this._protocolName = server.Name;
    }

    #region ICheck Members

    public void StartCheck()
    {
        Ping pingSender = new Ping();
        PingOptions options = new PingOptions();

        // Use the default Ttl value which is 128,
        // but change the fragmentation behavior.
        options.DontFragment = true;

        // Create a buffer of 32 bytes of data to be transmitted.
        string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
        byte[] buffer = Encoding.ASCII.GetBytes(data);
        int timeout = 120;

        PingReply reply = pingSender.Send(_serverIp, timeout, buffer, options);
        if (reply.Status == IPStatus.Success)
        {
            //Console.WriteLine("Address: {0}", reply.Address.ToString());
            //Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
            //Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
            //Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
            //Console.WriteLine("Buffer size: {0}", reply.Buffer.Length);
        }
        else
        {
            //Dump to log file and send by email
        }

        StopCheck();
    }

    public void StopCheck()
    {
        //to implement
    }

    #endregion

}





和最后一个用于触发动作的程序类:):




and at last Program class to fire actions :) :

class Program
  {
      static void Main(string[] args)
      {
          HeartbeatSupervisor dd;
          dd = new HeartbeatSupervisor(new Server("someserver", "127.0.0.1"), new Protocol("tcp"));
          dd.StartCheck(); //inside here ill use values passed to constructor
          //for Server and Protocol and do let say ping

      }
  }

推荐答案

毕竟我确实喜欢这样:



I did like this after all :

public abstract class Cocpit: ICheck
   {
 protected string id;
        protected virtual string Id
        {
            get { return id; }
            set { id = value; }
        }

        protected string name;
        protected virtual string Name
        {
            get { return name; }
            set { name = value; }
        }





服务器我做了:(不需要实现自己的条件只需使用值



in Server I did: (no need to implement own condition just use values

public class Server: Cocpit
   {
  public Server(string name, string ip)
            : base(name)
        {
            base.Id = ip;     //could be without base word
            base.Name = name;

        }





在协议I中实现Id的新条件



inside Protocol I implemented new conditions for Id

public class Protocol: Cocpit
{

    /// This constructor will call Cocpit.Cocpit()
    public Protocol(string name)
        : base(name)
    {
        base.Name = "dd";
    }

 protected override string Id
        {

            get { return null; }

            set
            {
                //dont need to use base word
                if (base.id != value) return;
                //DoSomethingOnWrite(id, value);
                base.id = value;
            } //set Id

        }





毕竟想要在Heartbeate中使用我无法访问protocol.Name里面的构造函数 - 如何访问它?





and after all when want to use inside Heartbeate I cant access protocol.Name inside constructor - how to access that?

 this._protocolName = protocol.Name;
}







public class HeartbeatSupervisor : ICheck
 {

     private string _serverIp;
     private string _protocolName;

     protected string ServerIp
     {
         get { return _serverIp; }
         set { _serverIp = value; }
     }

     protected string ProtocolName
     {
         get { return _protocolName; }
         set { _protocolName = value; }
     }

     public HeartbeatSupervisor(Server server, Protocol protocol)
     {
        this._serverIp = server.Ip;
        this._protocolName = protocol.Name;
     }


carlito_brigante写道:
carlito_brigante wrote:

所以要充分确定我的想法是否正确请告诉我或者不是我的两个陈述:第一种情况:我从一开始就不知道从抽象基类继承的派生类是否需要控制值,所以如果有的话,我会像下面那样实现派生类不想控制值然后不需要覆盖它,但只是直接从抽象基类使用Id,就是这样但是如果某个派生类想要控制Id那么需要覆盖它自己的Id并创建私有field _id以及...

So to be fully sure my thinking is really correct please tell yes or not to my two statements: First case: I don't know since beginning whether derived classes inheriting from abstract base class would need to control values or not so I would implement like below then if some derived class don't want to control value then don't need to override this but just use Id directly from abstract base class and that's it but if some derived class would like to control Id then need to override Id for it own and create private field _id as well…

错误。



让我们看看为什么你需要一个属性(不是字段)。你需要它只是因为它的setter或getter,或两者兼而有之,才能在读取或写入属性值时产生一些副作用。为什么有自动实现的属性(只有 {get; set;} 而不是真正的getter和setter?只是因为你想在将来保留这种可能性。 />


你考虑的第一个缺陷是:我从一开始就不知道继承自抽象基类的派生类是否需要控制值,所以......。如果你不知道,这意味着你应该假设派生类必须控制它。这不是很明显吗?



第二个大缺陷是你认为明确的支持字段可以添加任何东西。事实上,自动实现的支持严格等同于类似的显式支持(不包括微妙但实际上非常重要的名称问题)支持字段。。自动实现支持并不限制以任何方式添加这些副作用的能力。



我引用的评论中的代码不会甚至编译也行没有意义,所以我会写出正确的说明性例子:

Wrong.

Let's see why would you need a property (not field) at all. You need it only because of its setter, or getter, or both, to provide some side effect on reading or writing the property value. Why having auto-implemented properties (with just { get; set; } instead of "real" getter and setter? Just because you want to preserve such possibility in future.

Your first flaw in your consideration is: "I don't know since beginning whether derived classes inheriting from abstract base class would need to control values or not, so…". If you don't know that, it means that you should assume that the derived class will have to control it. Isn't it obvious?

The second big flaw is that you think that explicit backing fields can add anything at all. In fact, auto-implemented backing is strictly equivalent to similar explicit backing (not counting the subtle but practically non-considerable problem of the name of that backing field). Having auto-implemented backing does not limit the ability to add those side effects in any way.

Your code in the comment I referenced won't even compile and does not makes sense, so I'll write proper illustrative example:

abstract class MyAbstractClass {
    protected virtual string Id { get; set; } // no need in explicit backing, ever
} //class MyAbstractClass

// this class does nothing useful because it adds no functionality,
// so it does not make any sense:
class MyDerivedClassWhichDoesNothingUseful : MyAbstractClass {
    protected string _id;
    protected override string Id { get { return _id; } set { _id = value; } }
} //class MyDerivedClassWhichDoesNothingUseful

// overriding Id only makes sense if you introduce some side effect to the setter
// or to the getter, or both:
class MyDerivedClassWhichCanMakeSomeSense : MyAbstractClass {
    protected string id; // (name fixed to meet the Microsoft naming conventions)
    protected override string Id {
        get {
            DoSomethingOnRead(id);
            return id;
        } //getId
        set {
            if (id == value) return;
            DoSomethingOnWrite(id, value);
            id = value;
        } //set Id
    } //Id
    void DoSomethingOnRead(string value) { /* ... */ }
    void DoSomethingOnWrite(string oldValue, string newValue) { /* ... */ }
} //class MyDerivedClassWhichCanMakeSomeSense





现在是否清楚?



让我再次告诉你:你原来的代码是有问题的还有其他一些方法:接口的作用(仅在使用后期绑定时才需要) ,多态方法接收某些接口的参数编译时间,混合接口与虚方法/属性机制(没有错,但一切都应该有它的目的),等等。我只看到了第一眼看上去很明显的东西。



-SA



Is it clear now?

Let me tell you again: your original code is questionable is some other ways: the role of the interface (which is only needed when you use late binding, polymorphic methods receiving parameters of some interface compile-time, mixing interfaces with virtual method/property mechanisms (nothing wrong about it, but everything should have its purpose), and so on. I only caught what seemed obvious from the first glance.

—SA


这篇关于C#OOP继承类结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆