none
Dubbi su classi e puntatori RRS feed

  • Domanda

  • Ciao a Tutti.

    Magari la risposta è banale ma mi sto picchiando per realizzare un codice più elegante e meno rindondante.

    Ho 2 classi simili derivate dalla classe Form per le quali istanzio 2 oggetti che vado ad utilizzare a seconda che l'utente selezioni la modalità 1 o 2.


    public class Form1 : Form { public int GetNumber(); public char GetCharacter(); public void MetododiForm1(); } public class Form2 : Form { public int GetNumber(); public char GetCharacter(); public void MetododiForm2(); }

    public frm1=new Form1();

    public frm2=new Form2();

    if(condizione)

    frm1.GetNumber();

    else if (condizione2)

    frm2.GetNumber()

    il mio intento è, per gli oggetti creati appartenenti alle classi Form1 e Form2, di chiamare i metodi aventi lo stesso nome (e che servono allo stesso scopo, solo in modo diverso) senza dover specificare ogni volta la classe di provenienza, dato che sono costretto ogni volta a effettuare un check sulla scelta dell'utente (devo visualizzare il metodo di Form1 o Form2?).

    Pensavo inizialmente alle classi derivate ma essendo già derivate dalla classe Form non posso farlo (e c# non consente ereditarietà multipla).

    Ho provato con un interfaccia ma mi sono solo complicato la vita (potrei anche non aver applicato bene la cosa).

    Ovviamente ho cercato di sintetizzare il problema, il vero codice è molto ampio.

    Qualcuno mi chiarisce le idee?

    Grazie della vostra attenzione



    lunedì 30 settembre 2019 17:44

Risposte

  • Ereditare una classe che deriva da Form è possibile anche se non capisco bene la tua esigenza, 

    Nel senso che puoi creare una classe

    MyForm : Form

    e poi una classe

    MyChildForm : MyForm

    Se proprio ti serve derivare 2 volte. Però nel tuo caso non sarebbe più facile creare una Form sola e decidere la modalità in cui si apre con un parametro (una property della Form) che setti quando crei l'istanza della form e poi in base al parametro esegui il codice di tipo Uno o di tipo Due.

    public class MyForm : Form
    {
    
        public int Brhaviour {get; set;}
    
        public MethodOne()
        {
            switch( Behaviour )
            {
                case 1:
                    MethodForBehaviourOne();
                break;
                case 2:
                    MethodForBehaviourTwo();
                break;
                case 3:
                  // se ti servono altri tipi
                break;
            }
        }
    
        private MethodForBehaviourOne()
        {
            //Fai il codice di tipo uno
        }
    
        private MethodForBehaviourTwo()
        {
            //Fai il codice di tipo due
        }
    }
    
    
    //Per istanziare la classe qui sopra
    
    MyForm frm = new MyForm();
    frm.Behaviour = 1;
    frm.Show();
    
    
    
    
    
    

    Ovviamente puoi usare il controllo sul parametro di comportamento su qualsiasi metodo nella form come ad esempio gli event handler collegati a bottoni o altri componenti.

    saluti


    Sabrina C. - http://www.dotnetwork.it

    giovedì 3 ottobre 2019 17:45
  • personalmente in questi casi utilizzo le interfacce.

    L'interfaccia è un contratto che specifica la firma dei metodi e/o proprietà.

    es:

    public interface IMyContract
    {
       int GetNumber();
       char GetCharacter();
       void Show();
       string Description { get; }
    }

    dopo che ho definito il contratto posso implementarlo nei mie oggetti in maniera esplicita ed implicita.

        // Maniera Implicita
        public partial class Form1 : Form, IMyContract
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            #region IMyContract Members
    
            public int GetNumber()
            {
                return 1;
            }
    
            public char GetCharacter()
            {
                return 'a';
            }
    
            public string Description
            {
                get { return this.GetType().Name; }
            }
    
            #endregion
        }
    
        // Maniera esplicita
        public class Form2 : Form, IMyContract
        {
    
            #region IMyContract Members
    
            int IMyContract.GetNumber()
            {
                return 2;
            }
    
            char IMyContract.GetCharacter()
            {
                return 'b';
            }
    
            void IMyContract.Show()
            {
                this.Show();
            }
    
            string IMyContract.Description
            {
                get { return this.GetType().Name; }
            }
    
            #endregion
        }


    e poi puoi utilizzare cosi:

        public static class Factory
        {
            public static IMyContract GetIstance(string parameter)
            {
                IMyContract contract = null;
                switch (parameter)
                {
                    case "uno":
                        contract = new Form1();
                        break;
                    case "due":
                        contract = new Form2();
                        break;
    
                    default:
                        break;
                }
                return contract;
            }
        }
    
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main(string[] args)
            {
                if (args.Length == 0)
                {
                    var dialog = Factory.GetIstance(args[0]);
                    if (dialog != null)
                    {
                        dialog.Show();
                        var number = dialog.GetNumber();
                        var character = dialog.GetCharacter();
                        var description = dialog.Description;
    
                        MessageBox.Show($"{description} Number = {number}, Character={character}");
                    }
                }
                else
                {
                    MessageBox.Show("Invalid parameter");
                }
            }
        }


    Si può fare un ulteriore affinamento come hai visto l'implementazione del proprietà Description è uguale in tutte e due le classi, si potrebbe allora pensare di aggiungere una classe intermedia che implementi i metodi comuni:

    es: 

        public abstract class BaseForm: Form, IMyContract
        {
            #region IMyContract Members
    
            public abstract int GetNumber();
    
            public abstract char GetCharacter();
          
    
            public string Description
            {
                get { return this.GetType().Name; }
            }
    
            #endregion
        }
    
        public class Form1B:BaseForm
        {
    
            public override int GetNumber()
            {
                return 1;
            }
    
            public override char GetCharacter()
            {
                return 'a';
            }
        }
    
        public class Form2B : BaseForm
        {
    
            public override int GetNumber()
            {
                return 2;
            }
    
            public override char GetCharacter()
            {
                return 'b';
            }
        }

    Spero di essere stato esaustivo;

    P.S. la differenza fra implementazione esplicita ed implicita e che nella prima i metodi e le proprietà non fanno parte dell'interfaccia pubblica della classe derivata (non vedi i metodi nell'ide).

     
    venerdì 4 ottobre 2019 16:16

Tutte le risposte

  • Ereditare una classe che deriva da Form è possibile anche se non capisco bene la tua esigenza, 

    Nel senso che puoi creare una classe

    MyForm : Form

    e poi una classe

    MyChildForm : MyForm

    Se proprio ti serve derivare 2 volte. Però nel tuo caso non sarebbe più facile creare una Form sola e decidere la modalità in cui si apre con un parametro (una property della Form) che setti quando crei l'istanza della form e poi in base al parametro esegui il codice di tipo Uno o di tipo Due.

    public class MyForm : Form
    {
    
        public int Brhaviour {get; set;}
    
        public MethodOne()
        {
            switch( Behaviour )
            {
                case 1:
                    MethodForBehaviourOne();
                break;
                case 2:
                    MethodForBehaviourTwo();
                break;
                case 3:
                  // se ti servono altri tipi
                break;
            }
        }
    
        private MethodForBehaviourOne()
        {
            //Fai il codice di tipo uno
        }
    
        private MethodForBehaviourTwo()
        {
            //Fai il codice di tipo due
        }
    }
    
    
    //Per istanziare la classe qui sopra
    
    MyForm frm = new MyForm();
    frm.Behaviour = 1;
    frm.Show();
    
    
    
    
    
    

    Ovviamente puoi usare il controllo sul parametro di comportamento su qualsiasi metodo nella form come ad esempio gli event handler collegati a bottoni o altri componenti.

    saluti


    Sabrina C. - http://www.dotnetwork.it

    giovedì 3 ottobre 2019 17:45
  • personalmente in questi casi utilizzo le interfacce.

    L'interfaccia è un contratto che specifica la firma dei metodi e/o proprietà.

    es:

    public interface IMyContract
    {
       int GetNumber();
       char GetCharacter();
       void Show();
       string Description { get; }
    }

    dopo che ho definito il contratto posso implementarlo nei mie oggetti in maniera esplicita ed implicita.

        // Maniera Implicita
        public partial class Form1 : Form, IMyContract
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            #region IMyContract Members
    
            public int GetNumber()
            {
                return 1;
            }
    
            public char GetCharacter()
            {
                return 'a';
            }
    
            public string Description
            {
                get { return this.GetType().Name; }
            }
    
            #endregion
        }
    
        // Maniera esplicita
        public class Form2 : Form, IMyContract
        {
    
            #region IMyContract Members
    
            int IMyContract.GetNumber()
            {
                return 2;
            }
    
            char IMyContract.GetCharacter()
            {
                return 'b';
            }
    
            void IMyContract.Show()
            {
                this.Show();
            }
    
            string IMyContract.Description
            {
                get { return this.GetType().Name; }
            }
    
            #endregion
        }


    e poi puoi utilizzare cosi:

        public static class Factory
        {
            public static IMyContract GetIstance(string parameter)
            {
                IMyContract contract = null;
                switch (parameter)
                {
                    case "uno":
                        contract = new Form1();
                        break;
                    case "due":
                        contract = new Form2();
                        break;
    
                    default:
                        break;
                }
                return contract;
            }
        }
    
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main(string[] args)
            {
                if (args.Length == 0)
                {
                    var dialog = Factory.GetIstance(args[0]);
                    if (dialog != null)
                    {
                        dialog.Show();
                        var number = dialog.GetNumber();
                        var character = dialog.GetCharacter();
                        var description = dialog.Description;
    
                        MessageBox.Show($"{description} Number = {number}, Character={character}");
                    }
                }
                else
                {
                    MessageBox.Show("Invalid parameter");
                }
            }
        }


    Si può fare un ulteriore affinamento come hai visto l'implementazione del proprietà Description è uguale in tutte e due le classi, si potrebbe allora pensare di aggiungere una classe intermedia che implementi i metodi comuni:

    es: 

        public abstract class BaseForm: Form, IMyContract
        {
            #region IMyContract Members
    
            public abstract int GetNumber();
    
            public abstract char GetCharacter();
          
    
            public string Description
            {
                get { return this.GetType().Name; }
            }
    
            #endregion
        }
    
        public class Form1B:BaseForm
        {
    
            public override int GetNumber()
            {
                return 1;
            }
    
            public override char GetCharacter()
            {
                return 'a';
            }
        }
    
        public class Form2B : BaseForm
        {
    
            public override int GetNumber()
            {
                return 2;
            }
    
            public override char GetCharacter()
            {
                return 'b';
            }
        }

    Spero di essere stato esaustivo;

    P.S. la differenza fra implementazione esplicita ed implicita e che nella prima i metodi e le proprietà non fanno parte dell'interfaccia pubblica della classe derivata (non vedi i metodi nell'ide).

     
    venerdì 4 ottobre 2019 16:16