Visualizzazione dei risultati da 1 a 9 su 9
  1. #1
    Utente di HTML.it L'avatar di a.felix
    Registrato dal
    Sep 2001
    Messaggi
    337

    [C#] Classi astratte e costruttori

    Ciao, ho una classe astratta che implementa un'interfaccia,

    esempio, iPearson[interfaccia] viene implementata da aPearson[astratta],
    voglio ora ereditare l'astratta su "Developer","Architect", ecc (lo sò esempi del cavolo )..

    ma non trovo il modo di creare un mio costruttore parametrizzato su aPearson per far si di non dover ripetere "Name=name;Surname=surname;..." ecc ecc giusto per pulire un pò il codice..

    si può fare? e come?

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,474
    Per quanto ne so, nelle classi discendenti è sempre necessario ridefinire i costruttori che si vogliono rendere disponibili, ma potrei ricordare male (in altri linguaggi, come Delphi, questo non è necessario, quindi è possibile che vi sia una scorciatoia anche in C#).
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Utente di HTML.it L'avatar di a.felix
    Registrato dal
    Sep 2001
    Messaggi
    337
    si infatti sapevo che in java vi è un modo per ovviare, ma in c# mi sà di no a questo punto ..



    chi mi stupisce con una soluzione???

  4. #4
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    al massimo puoi fare cosi (non ho l'ide sottomano perciò potrei digitare qualcosa in modo impreciso):

    codice:
    //Costruttore di Developer
    //Nome e Cognome sono proprietà della clase base 
    //La classe base APerson ha un costruttore che accetta due parametri stringa.
    public Develoer(string nome, string cognome, string linguaggio) : base(nome, cognome)
    {
        this.Linguaggio = linguaggio;
    }

  5. #5
    Utente di HTML.it L'avatar di U235
    Registrato dal
    Mar 2006
    Messaggi
    1,539

    Re: [C#] Classi astratte e costruttori

    Originariamente inviato da a.felix
    Ciao, ho una classe astratta che implementa un'interfaccia,

    esempio, iPearson[interfaccia] viene implementata da aPearson[astratta],
    voglio ora ereditare l'astratta su "Developer","Architect", ecc (lo sò esempi del cavolo )..

    ma non trovo il modo di creare un mio costruttore parametrizzato su aPearson per far si di non dover ripetere "Name=name;Surname=surname;..." ecc ecc giusto per pulire un pò il codice..

    si può fare? e come?
    ciao,

    in teoria si...
    in pratica non so se ti conviene a livello di prestazioni...
    comunque l'idea che mi è venuta in mente è nata da dei test che sto facendo. è questa :

    codice:
    namespace Test
    {
        public partial class Form2 : Form
        {
            public Form2()
            {
                InitializeComponent();
                Dictionary<string, string> dizionario = new Dictionary<string, string>();
                dizionario.Add("professione", "Sono un developer!");
                APearson Developer = EstendiAstratta("pippo ", "paperino", "Developer", "Test", dizionario, "public override string GetFullName() { return Name+Surname; }");
                MessageBox.Show(Developer.GetFullName());
                APearson Developer2 = EstendiAstratta("pippo ", "paperino", "Developer2", "Test", dizionario, "public override string GetFullName() { return professione; }");
                MessageBox.Show(Developer2.GetFullName());
                dizionario["professione"] = "Sono un Architect";
                APearson Architect = EstendiAstratta("pippo ", "paperino", "Architect", "Test", dizionario, "public override string GetFullName() { return Name+Surname; }");
                MessageBox.Show(Architect.GetFullName());
                APearson Architect2 = EstendiAstratta("pippo ", "paperino", "Architect2", "Test", dizionario, "public override string GetFullName() { return professione; }");
                MessageBox.Show(Architect2.GetFullName());
            }
    
            public static APearson EstendiAstratta(string name, string surname, string nomeClasse, string nameSpace, Dictionary<string, string> proprieta, string voidGetFullName)
            {
                CSharpCodeProvider CSharpCodeProvider = new CSharpCodeProvider();
                ICodeCompiler Compilatore = CSharpCodeProvider.CreateCompiler();
                CompilerParameters ParametriCompilatore = new CompilerParameters();
                ParametriCompilatore.GenerateInMemory = true;
                ParametriCompilatore.IncludeDebugInformation = true;
                foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
                {
                    try
                    {
                        ParametriCompilatore.ReferencedAssemblies.Add(asm.Location);
                    }
                    catch
                    {
                        return null;
                    }
                }
                StringBuilder CodiceSorgente = new StringBuilder();
                CodiceSorgente.Append("using System;");
                CodiceSorgente.Append("\n");
                CodiceSorgente.Append("using System.Collections.Generic;");
                CodiceSorgente.Append("\n");
                CodiceSorgente.Append("using Test;");
                CodiceSorgente.Append("\n");
                CodiceSorgente.Append("using System.Text;");
                CodiceSorgente.Append("\n");
                CodiceSorgente.Append("using Microsoft.CSharp;");
                CodiceSorgente.Append("\n");
                CodiceSorgente.Append("using System.CodeDom.Compiler;");
                CodiceSorgente.Append("\n");
                CodiceSorgente.Append("namespace "); CodiceSorgente.Append(nameSpace);
                CodiceSorgente.Append("\n");
                CodiceSorgente.Append("{\n");
                CodiceSorgente.Append("public class "); CodiceSorgente.Append(nomeClasse);
                CodiceSorgente.Append(" : "); CodiceSorgente.Append(typeof(APearson));
                CodiceSorgente.Append("\n");
                CodiceSorgente.Append("{\n");
                foreach (string nomeProprieta in proprieta.Keys)
                {
                    string nomeProprietaMaiuscola = nomeProprieta.Substring(0, 1).ToUpper() + nomeProprieta.Substring(1, nomeProprieta.Length - 1);
                    string minuscola = nomeProprieta.Substring(0, 1).ToLower() + nomeProprieta.Substring(1, nomeProprieta.Length - 1);
                    CodiceSorgente.Append("public string "); CodiceSorgente.Append(nomeProprietaMaiuscola);
                    CodiceSorgente.Append("{ get{ return " + minuscola + ";} set{ " + minuscola + " = value; }}"); CodiceSorgente.Append("\n");
                    CodiceSorgente.Append("\n");
                    CodiceSorgente.Append("string ");
                    CodiceSorgente.Append(minuscola); CodiceSorgente.Append(" = ");
                    CodiceSorgente.Append(@""""); CodiceSorgente.Append(proprieta[nomeProprieta]); CodiceSorgente.Append(@"""");
                    CodiceSorgente.Append(";");
                }
                CodiceSorgente.Append("public "); CodiceSorgente.Append(nomeClasse); CodiceSorgente.Append("(string name, string surname) : base(name,surname){}");
                CodiceSorgente.Append(voidGetFullName);
                CodiceSorgente.Append("\n}}");
                CompilerResults RisultatoCompilatore = Compilatore.CompileAssemblyFromSource(ParametriCompilatore, CodiceSorgente.ToString());
                if (RisultatoCompilatore.Errors.HasErrors)
                {
                    foreach (CompilerError Errore in RisultatoCompilatore.Errors)
                    {
                        if (!Errore.IsWarning)
                        {
                            return null;
                        }
                    }
                }
                Type t = null;
                for (int i = 0; i < RisultatoCompilatore.CompiledAssembly.GetTypes().Length; i++)
                {
                    if (RisultatoCompilatore.CompiledAssembly.GetTypes()[i].Name == nomeClasse)
                    {
                        t = RisultatoCompilatore.CompiledAssembly.GetTypes()[i];
                        break;
                    }
                }
                return (APearson)t.InvokeMember(nomeClasse, System.Reflection.BindingFlags.CreateInstance, null, null, new object[] { name, surname });
            }
        }
        public interface IPearson
        {
            string Name { get; set; }
            string Surname { get; set; }
    
            string GetFullName();
        }
    
        public abstract class APearson : IPearson
        {
            public string Name { get; set; }
            public string Surname { get; set; }
    
            public APearson(string name, string surname)
            {
                this.Name = name;
                this.Surname = surname;
            }
    
            public abstract string GetFullName();
        }
    }
    ovviamente è buttata giù al volo, e sostanzialmente si tratta di usare

    EstendiAstratta("pippo ", "paperino", "Developer", "Test", dizionario, "public override string GetFullName() { return Name+Surname; }");

    volendo ridurre i parametri potresti arrivare ad averne anche solo a due... io qui ho voluto mettere l'override di un metodo e l'aggiunta di proprietà string, oltre al nome classe e il namespace.

    spero che per la soluzione proposta non mi fustighiate pubblicamente in "piazza OT"


    p.s. se non è comprensibile fammi sapere.

  6. #6
    Utente di HTML.it L'avatar di a.felix
    Registrato dal
    Sep 2001
    Messaggi
    337
    Grazie della risposta
    effettivamente ho cominciato a capire alla 3° rilettura

    quello che volevo ottenere era semplicemnte questo

    codice:
        public interface iPearson
        {
    
            string Name { get; set; }
            string Surname { get; set; }
            string AddressWay { get; set; }
            string AddressCity { get; set; }
            //chiamato APearson ... ma giusto per esempio
            private APearson(string name, string surname, string addressWay, string addressCity);
        }
        public abstract class APearson : iPearson
        {
            public string Name { get; set; }
            public string Surname { get; set; }
            public string AddressWay { get; set; }
            public string AddressCity { get; set; }
            //Questo poi deve diventare il costruttore di Client
            private APearson(string name, string surname, string addressWay, string addressCity)
            {
                Name = name;
                Surname = Surname;
                AddressWay = addressWay;
                AddressCity = addressCity;
            }
    
        }
        public class Client : APearson
        {
            public void  Varie()
            {
    
            }
    
        }
    Forse così si capisce..

  7. #7
    Utente di HTML.it L'avatar di U235
    Registrato dal
    Mar 2006
    Messaggi
    1,539

    Re: [C#] Classi astratte e costruttori

    Avevo capito tutto eh! evviva il bias di conferma

    mi sa tanto che non si può far nulla...

  8. #8
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    Mettere questo costruttore prima di Varie()? non mi sembra tanto "sporco" come codice
    codice:
    public Client(string name, string surname, string addressWay, string addressCity)
        : base(string name, string surname, string addressWay, string addressCity)
            { }
    E' l'unica cosa che puoi fare, e mi sembra pure giusto. Pensa se potessi richiamare "di nascosto" il costruttore della classe base durante l'istanziamento della classe Client: Se nella Client avessi bisogno di un costruttore tipo questo:

    codice:
    //NOTA: stessa firma del costruttore di APerson
    public Client(string banca, string commerciale, string blabla, string blablabla)
    { 
        //Implemetazione
    }
    Cosa verrebbe richiamato quando scrivi:
    codice:
     Client cliente = new Cliente("pippo", "baudo","pluto", "paperino");
    ...il costruttore di Client o quello di APerson? E se esistesse una regola (tipo: si possono richiamare i costruttori delle basi ma solo se la derivata non ha un costruttore con la stessa firma altrimenti viene chiamato quello della derivata) per me sarebbe un casino...

    E se volessimo usare il Late binding?
    codice:
    //Giusto, ma non risolve il problema
    APerson cliente = new Cliente("pippo", "baudo","pluto", "paperino");
    
    //Risolverebbe il problema, potrebbe anche funzionare, ma teoricamente non è giusto (e non so nemmeno se c# te lo fa compilare), il motivo è ovvio, la derivata potrebbe avere delle proprietà che DEVONO essere istanziate e questo non può essere fatto dalla classe base.
    Clente cliente = new Aperson("pippo", "baudo","pluto", "paperino") as Client;
    La soluzione: Visto che molti programmatori perdevano tempo a scrivere costruttori parametrizzati C# dalla versione 4.0 permette di istanziare classi in questo modo:
    codice:
    Client cliente = new Client(Nome = "Pippo", Cognome = "pluto");
    Funziona solo con le proprietà pubbliche e viene SEMPRE richiamato l'unico costruttore di default (il quale magari deve istanziare le collection o le proprietà private).

    Personalmente (ma molto personalmente) non utilizzo mai se non con parsimonia questo sistema, può essere comodo in certe occasioni ma per tutto il resto preferisco il vecchio sistema (quello che ti ho scritto all'inizio).

  9. #9
    Utente di HTML.it L'avatar di a.felix
    Registrato dal
    Sep 2001
    Messaggi
    337
    Originariamente inviato da rsdpzed
    Mettere questo costruttore prima di Varie()? non mi sembra tanto "sporco" come codice
    codice:
    public Client(string name, string surname, string addressWay, string addressCity)
        : base(string name, string surname, string addressWay, string addressCity)
            { }
    si nn intendevo sporco in quel senso, ma essendo molto più complesso e sempre uguale per tutte le classi volevo evitare.
    E' l'unica cosa che puoi fare, e mi sembra pure giusto. Pensa se potessi richiamare "di nascosto" il costruttore della classe base durante l'istanziamento della classe Client: Se nella Client avessi bisogno di un costruttore tipo questo:

    codice:
    //NOTA: stessa firma del costruttore di APerson
    public Client(string banca, string commerciale, string blabla, string blablabla)
    { 
        //Implemetazione
    }
    Cosa verrebbe richiamato quando scrivi:
    codice:
     Client cliente = new Cliente("pippo", "baudo","pluto", "paperino");
    ...il costruttore di Client o quello di APerson? E se esistesse una regola (tipo: si possono richiamare i costruttori delle basi ma solo se la derivata non ha un costruttore con la stessa firma altrimenti viene chiamato quello della derivata) per me sarebbe un casino...

    E se volessimo usare il Late binding?
    codice:
    //Giusto, ma non risolve il problema
    APerson cliente = new Cliente("pippo", "baudo","pluto", "paperino");
    
    //Risolverebbe il problema, potrebbe anche funzionare, ma teoricamente non è giusto (e non so nemmeno se c# te lo fa compilare), il motivo è ovvio, la derivata potrebbe avere delle proprietà che DEVONO essere istanziate e questo non può essere fatto dalla classe base.
    Clente cliente = new Aperson("pippo", "baudo","pluto", "paperino") as Client;
    La soluzione: Visto che molti programmatori perdevano tempo a scrivere costruttori parametrizzati C# dalla versione 4.0 permette di istanziare classi in questo modo:
    codice:
    Client cliente = new Client(Nome = "Pippo", Cognome = "pluto");
    Funziona solo con le proprietà pubbliche e viene SEMPRE richiamato l'unico costruttore di default (il quale magari deve istanziare le collection o le proprietà private).

    Personalmente (ma molto personalmente) non utilizzo mai se non con parsimonia questo sistema, può essere comodo in certe occasioni ma per tutto il resto preferisco il vecchio sistema (quello che ti ho scritto all'inizio).
    Non conoscevo quest'ultimo ma non lo posso usare per problemi di compatibilità del FW ma buono a sapersi, grazie degli altri esempi ..ora valuto e cerco di capire come fare

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.