Chiarimento sul polimorfismo / ereditarietà

1

Sto cercando di migliorare la mia comprensione del polimorfismo.

Dire che ho una classe base chiamata baseClass con un metodo chiamato foo() e ho tre classi derivate chiamate derived1 , derived2 e derived3 che sovrascrivono e implementano le loro versioni della% metodofoo().

Se ho una matrice di oggetti baseClass può contenere oggetti derivati da tale classe base in questo modo:

baseClassArray: [ derivedObj1, derivedObj2, derivedObj3];

Inoltre, se estraggo un oggetto da questa matrice e chiamo il metodo foo() , chiamerebbe il metodo definito in baseClass o il metodo definito nella rispettiva classe derivata?

O questo dipende dal linguaggio di programmazione in cui è implementato?

    
posta The_Neo 19.02.2014 - 20:34
fonte

5 risposte

3
  • Stai descrivendo il polimorfismo. Stai usando la classe base come interfaccia. Quindi il tuo esempio è come:

((BaseClass)baseClassArray[0]).foo()

o

((BaseClass)derivedObj1).foo()

Il metodo foo () è definito dalla classe base, ma l'implementazione si trova nella sottoclasse, almeno nel tuo esempio. In OO, se una sottoclasse sovrascrive un metodo, allora diventa l'implementazione che viene chiamata.

  • L'ereditarietà è un po 'diversa. Supponiamo che tu abbia un derivatoObj4 che non sovrascrive foo (). Quindi puoi chiamare:

((SubClass)derivedObj4).foo()

che prima cercherebbe in derivedObj4, vedi che foo () non c'è, quindi guarda BaseClass per l'implementazione.

    Il polimorfismo
  • può contare sull'ereditarietà, il che lo rende un po 'confuso.

  • L'idea alla base del polimorfismo è che la classe base definisce i metodi e le sottoclassi definiscono l'implementazione. (Anche se possono ancora ereditare l'implementazione.) In altre parole, la classe base maschera la sottoclasse, ma la sottoclasse fa il lavoro.

  • L'idea dietro l'ereditarietà è che la sottoclasse è l'interfaccia, ma eredita l'implementazione dalla classe base, quindi non è necessario implementarla. La sottoclasse maschera la classe base, ma la classe base fa il lavoro.

risposta data 19.02.2014 - 21:11
fonte
1

Il metodo effettivo chiamato sarà determinato in fase di esecuzione a seconda del tipo di oggetto. Se hai una matrice di oggetti di tipo baseClass (che può includere tipi ereditati) il metodo che viene chiamato sarà il metodo foo () di qualunque tipo sia l'oggetto.

Quindi gli oggetti che sono di tipo baseClass avranno l'implementazione della classe base di foo () chiamata. Se i tuoi oggetti sono uno dei tipi derivati e gli oggetti derivati sovrascrivono il metodo foo () questo sarà chiamato. Se gli oggetti derivati non sovrascrivono il metodo foo (), verrà chiamato il metodo della classe base foo ().

    
risposta data 19.02.2014 - 20:56
fonte
1

Questo dovrebbe funzionare, ma è specifico per la lingua. ciò a cui ti riferisci è un "upcast", prendendo gli oggetti derivati e riconducendoli alla classe base. A seconda della lingua, dovrai eseguire il cast ex:

derived1 obj1 = new derived1();

baseClass base[10];

base[0] = (baseClass)obj1;

quando chiami il metodo foo () verrà usato baseClass foo () a meno che tu non esegua e aggiunga "downcast" ex:

derived1 sameobj1 = (derived1)base[0];

dopo aver eseguito il downcast verrà chiamato il metodo foo () per derived1. alcune lingue possono utilizzare l'operatore di confronto "typeOf" invece di upcasting e downcasting ex:

if( obj1 typeOf baseClass)

base[0] = obj1; // no casting necessary

quindi quando li estrai dalla base di array chiama semplicemente foo () e viene chiamato foo () per ogni classe derivata.

foreach( obj in base)

obj.foo()

questo chiamerà il metodo foo () per ogni classe derivata.

    
risposta data 19.02.2014 - 20:55
fonte
1

Inheritance

// this is pseudo code - isn

// base class references to derived-type objects.
BaseClass thing1 = new Derived1();
BaseClass thing2 = new Derived2();
BaseClass thing3 = new Derived3();

// assume the array elements must be of the same type
baseClassArray : [thing1, thing2, thing3];

for (int i-0; i< baseClassArray.Length; i++) {
    baseClassArray[i].Foo(); // base.Foo() is called.
}

for (int i=0; i< baseClassArray.Length; i++) {
    if (baseClassArray[i] is Derived1) {
        Derived1 thingy1 = (Derived1)baseClassArray[i];
        thingy1.Foo();   // the over-ride Foo() called
    }else if ....
}

Il polimorfismo

// this is pseudo code - ish

public abstract class AbstractPainter {
   public abstract void Style();
}

public class Dali : AbstractPainter {
    public override Style() {
        console.writeline("floppy clocks lying about");
}

public class Warhol : AbstractPainter {
    public override Style() {
        console.writeline("High contrast soup cans");
    }
}

// cannot instantiate abstract classes
// ie.  new AbstractPainter() is not allowed.

AbstractPainter Salvador = new Dali();
AbstractPainter Andy = new Warhol();

AbstractPainterArray = [Salvador, Andy];

for (int i=0; i< AbstractPainterArray.Length; i++) {
    AbstractPainterArray[i].Style();
}

output:
    "floppy clocks lying about"
    "High contrast soup cans"

Take Away?

Ereditarietà: riferimenti dello stesso tipo + oggetti derivati, stessa chiamata al metodo.

polimorfismo

: riferimenti dello stesso tipo + oggetti derivati, chiamata metodo differente.

    
risposta data 20.02.2014 - 03:07
fonte
0

Il metodo virtuale chiamato dipende sempre dal tipo di istanza concreta in memoria e mai da come si accede a questa istanza o dal tipo di variabile a cui si accede l'istanza. Il tipo di variabile dice semplicemente al compilatore quali classi e le sue sottoclassi possono essere salvate e quali metodi virtuali possono essere chiamati. Ma quale metodo viene effettivamente chiamato è noto solo dalla memoria in fase di runtime.

    
risposta data 19.02.2014 - 20:45
fonte

Leggi altre domande sui tag