Nedkastande
I klassbaserad programmering är nedkastning eller typförfining handlingen att gjuta en referens för en basklass till en av dess härledda klasser.
I många programmeringsspråk är det möjligt att kontrollera genom typintrospektion för att avgöra om typen av det refererade objektet verkligen är den som castas till eller en härledd typ av det, och därmed utfärda ett fel om så inte är fallet.
Med andra ord, när en variabel i basklassen ( förälderklass ) har ett värde för den härledda klassen ( barnklass ), är nedsändning möjlig.
Vissa språk, som OCaml , tillåter inte nedsändning.
Exempel
Java
public class Fruit {} // parent class public class Apple extends Fruit {} // child class public static void main ( String [] args ) { // Följande är en implicit uppsändning: Fruit parent = new Apple (); // Följande är en nedslagen. Här fungerar det eftersom variabeln `parent` är // som innehåller en instans av Apple: Apple child = ( Apple ) parent ; //Där Apple är barnklass men frukt är föräldraklass }
C++
// Föräldraklass: class Fruit { public : // Måste vara polymorf för att använda runtime-checked dynamic-cast. virtuell ~ Fruit () = default ; }; // Barnklass: klass Apple : public Fruit {}; int main ( int argc , const char ** argv ) { // Följande är en implicit uppsändning: Fruit * parent = new Apple (); // Följande är en nedslagen. Här fungerar det eftersom variabeln `parent` är // som innehåller en instans av Apple: Apple * child = dynamic_cast < Apple *> ( parent ); }
Används
Nedsändning är användbart när typen av värde som refereras till av den överordnade variabeln är känd och används ofta när ett värde skickas som en parameter. I exemplet nedan tar metoden objectToString en Object-parameter som antas vara av typen String.
public static String objectToString ( Object myObject ) { // Detta fungerar bara när det myObject som för närvarande håller värdet är string. return ( String ) myObject ; } public static void main ( String [] args ) { // Detta kommer att fungera sedan vi passerade i String, så myObject har värdet av String. String result = objectToString ( "Min sträng" ); Objekt iFail = nytt objekt (); // Detta kommer att misslyckas eftersom vi skickade in Object som inte har värdet av String. result = objectToString ( iFail ); }
I detta tillvägagångssätt förhindrar nedsändning kompilatorn från att upptäcka ett möjligt fel och orsakar istället ett körtidsfel. Nedsändning av myObject till String ('(String)myObject') var inte möjligt vid kompileringstillfället eftersom det finns tillfällen då myObject är av String-typ, så endast vid körning kan vi ta reda på om parametern som skickas in är logisk. Även om vi också kunde konvertera myObject till en kompilerings-tidssträng med den universella java.lang.Object.toString(), skulle detta riskera att anropa standardimplementeringen av toString() där den var ohjälpsam eller osäker, och undantagshantering kunde inte förhindra detta .
I C++ implementeras typkontroll av körtid genom dynamic_cast . Nedsändning av kompileringstid implementeras av static_cast , men denna operation utför ingen typkontroll. Om den används felaktigt kan den ge odefinierat beteende.
Överväganden
Ett populärt exempel på en dåligt övervägd design är behållare av topptyper , [ citat behövs ] som Java- behållarna innan Java-generika introducerades, vilket kräver nedkastning av de inneslutna objekten så att de kan användas igen.
Se även
externa länkar
- Downcasting is a Code Smell av Jeremy D. Miller
- En nedslående tragedi av Jimmy Bogard
- Föredrar polymorfism framför instanser av och nedkastning av Bill Venners
- Downcasting i C# av Scott Lysle
- Flera nedkastningstekniker
- Upcasting, downcasting av Sinipull