Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ «Ѐилософия Java3Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 47

Автор Π‘Ρ€ΡŽΡ ЭккСль

// polymorphism/PolyConstructors java // ΠšΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ‚ΠΎΡ€Ρ‹ ΠΈ ΠΏΠΎΠ»ΠΈΠΌΠΎΡ€Ρ„ΠΈΠ·ΠΌ Π΄Π°ΡŽΡ‚ Π½Π΅ Ρ‚ΠΎΡ‚ // Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ Π±Ρ‹ ΠΎΠΆΠΈΠ΄Π°Ρ‚ΡŒ import static net mindview util Print *.

class Glyph {

void drawO { print("Glyph drawO"), } GlyphO {

printCGlyphO ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ drawO");

drawO.

print ("GlyphO послС Π²Ρ‹Π·ΠΎΠ²Π° drawO").

class RoundGlyph extends Glyph { private int radius = 1; RoundGlyph(int r) { radius = r.

print("RoundGlyph RoundGlyph(). radius = " + radius);

}

void drawO {

print ("RoundGlyph. drawO, radius = " + radius);

public class PolyConstructors {

public static void main(String[] args) { new RoundGlyph(5);

}

} /* Output-

GlyphO ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ drawO RoundGlyph drawO, radius = 0 GlyphO послС Π²Ρ‹Π·ΠΎΠ²Π° drawO RoundGlyph RoundGlyphO, radius = 5 *///:-

ΠœΠ΅Ρ‚ΠΎΠ΄ Glyph.draw() ΠΈΠ·Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ для пСрСопрСдСлСния Π² ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½Ρ‹Ρ… классах, Ρ‡Ρ‚ΠΎ ΠΈ происходит Π² RoundGlyph. Но конструктор Glyph Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ этот ΠΌΠ΅Ρ‚ΠΎΠ΄, ΠΈ Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ это ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ Π²Ρ‹Π·ΠΎΠ²Ρƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° RoundGlyph.draw(), Ρ‡Ρ‚ΠΎ Π²Ρ€ΠΎΠ΄Π΅ Π±Ρ‹ ΠΈ ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π»ΠΎΡΡŒ. Однако ΠΈΠ· Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π²ΠΈΠ΄Π½ΠΎ β€” ΠΊΠΎΠ³Π΄Π° конструктор класса Glyph Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄ draw(), ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ radius Π΅Ρ‰Π΅ Π½Π΅ присвоСно Π΄Π°ΠΆΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ 1. ΠŸΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Π°Ρ Ρ€Π°Π²Π½Π° 0. Π’ ΠΈΡ‚ΠΎΠ³Π΅ класс ΠΌΠΎΠΆΠ΅Ρ‚ Π½Π΅ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ свою Π·Π°Π΄Π°Ρ‡Ρƒ, Π° Π²Π°ΠΌ придСтся Π΄ΠΎΠ»Π³ΠΎ Π²ΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒΡΡ Π² ΠΊΠΎΠ΄ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Ρƒ Π½Π΅Π²Π΅Ρ€Π½ΠΎΠ³ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°.

ΠŸΠΎΡ€ΡΠ΄ΠΎΠΊ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ, описанный Π² ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΌ Ρ€Π°Π·Π΄Π΅Π»Π΅, Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ Π½Π΅ΠΏΠΎΠ»ΠΎΠ½, ΠΈ ΠΈΠΌΠ΅Π½Π½ΠΎ здСсь кроСтся ΠΊΠ»ΡŽΡ‡ ΠΊ этой Π·Π°Π³Π°Π΄ΠΊΠ΅. На самом Π΄Π΅Π»Π΅ процСсс ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΡ€ΠΎΡ…ΠΎΠ΄ΠΈΡ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

β€’ ΠŸΠ°ΠΌΡΡ‚ΡŒ, выдСлСнная ΠΏΠΎΠ΄ Π½ΠΎΠ²Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, заполняСтся Π΄Π²ΠΎΠΈΡ‡Π½Ρ‹ΠΌΠΈ нулями.

β€’ ΠšΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ‚ΠΎΡ€Ρ‹ Π±Π°Π·ΠΎΠ²Ρ‹Ρ… классов Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‚ΡΡ Π² описанном Ρ€Π°Π½Π΅Π΅ порядкС. Π’ этот ΠΌΠΎΠΌΠ΅Π½Ρ‚ вызываСтся ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ draw() (Π΄Π°, ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ конструктора класса RoundGlyph), Π³Π΄Π΅ обнаруТиваСтся, Ρ‡Ρ‚ΠΎ пСрСмСнная radius Ρ€Π°Π²Π½Π° Π½ΡƒΠ»ΡŽ ΠΈΠ·-Π·Π° ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ этапа.

β€’ Π’Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‚ΡΡ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€Ρ‹ Ρ‡Π»Π΅Π½ΠΎΠ² класса Π² порядкС ΠΈΡ… опрСдСлСния.

β€’ Π˜ΡΠΏΠΎΠ»Π½ΡΠ΅Ρ‚ся Ρ‚Π΅Π»ΠΎ конструктора ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½ΠΎΠ³ΠΎ класса.

Π£ происходящСго Π΅ΡΡ‚ΡŒ ΠΈ ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ сторона β€” ΠΏΠΎ ΠΊΡ€Π°ΠΉΠ½Π΅ΠΉ ΠΌΠ΅Ρ€Π΅, Π΄Π°Π½Π½Ρ‹Π΅ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΡŽΡ‚ΡΡ нулями (ΠΈΠ»ΠΈ Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ понимаСтся ΠΏΠΎΠ΄ Π½ΡƒΠ»Π΅Π²Ρ‹ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ для ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° Π΄Π°Π½Π½Ρ‹Ρ…), Π° Π½Π΅ случайным «мусором» Π² памяти. Π­Ρ‚ΠΎ относится ΠΈ ΠΊ ссылкам Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹, Π²Π½Π΅Π΄Ρ€Π΅Π½Π½Ρ‹Π΅ Π² класс с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ. Они ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ особоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ null. Если Π²Ρ‹ Π·Π°Π±ΡƒΠ΄Π΅Ρ‚Π΅ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π°ΠΊΡƒΡŽ ссылку, Ρ‚ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π²ΠΎ врСмя выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. ΠžΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ Π·Π°ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ нулями, Π° это ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Π»Π΅Π³ΠΊΠΎ Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ ΠΏΠΎ Π²Ρ‹Ρ…ΠΎΠ΄Π½Ρ‹ΠΌ Π΄Π°Π½Π½Ρ‹ΠΌ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹.

Π‘ Π΄Ρ€ΡƒΠ³ΠΎΠΉ стороны, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ выглядит довольно ΠΆΡƒΡ‚ΠΊΠΎ. Π’Ρ€ΠΎΠ΄Π΅ Π±Ρ‹ всС Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ, Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ Π²Π΅Π΄Π΅Ρ‚ сСбя Π·Π°Π³Π°Π΄ΠΎΡ‡Π½ΠΎ ΠΈ Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ Π±Π΅Π· ΠΌΠ°Π»Π΅ΠΉΡˆΠΈΡ… объяснСний со стороны компилятора. (Π’ языкС Π‘++ Ρ‚Π°ΠΊΠΈΠ΅ ситуации ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ Π±ΠΎΠ»Π΅Π΅ Ρ€Π°Ρ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΌ способом.) Поиск ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹Ρ… ошибок Π·Π°Π½ΠΈΠΌΠ°Π΅Ρ‚ ΠΌΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ.

ΠŸΡ€ΠΈ написании конструктора Ρ€ΡƒΠΊΠΎΠ²ΠΎΠ΄ΡΡ‚Π²ΡƒΠΉΡ‚Π΅ΡΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ: Π½Π΅ ΠΏΡ‹Ρ‚Π°ΠΉΡ‚Π΅ΡΡŒ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ большС для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ привСсти ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π² Π½ΡƒΠΆΠ½ΠΎΠ΅ состояниС, ΠΈ ΠΏΠΎ возмоТности ΠΈΠ·Π±Π΅Π³Π°ΠΉΡ‚Π΅ Π²Ρ‹Π·ΠΎΠ²Π° ΠΊΠ°ΠΊΠΈΡ…-Π»ΠΈΠ±ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ². ЕдинствСнныС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ Π² конструкторС Π±Π΅Π· опаски β€” Π½Π΅ΠΈΠ·ΠΌΠ΅Π½Π½Ρ‹Π΅ (final) ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ класса. (Π‘ΠΊΠ°Π·Π°Π½Π½ΠΎΠ΅ относится ΠΈ ΠΊ Π·Π°ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΌ (private) ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ½ΠΈ автоматичСски ΡΠ²Π»ΡΡŽΡ‚ΡΡ Π½Π΅ΠΈΠ·ΠΌΠ΅Π½Π½Ρ‹ΠΌΠΈ.) Π’Π°ΠΊΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ, ΠΈ поэтому ΠΎΠ½ΠΈ застрахованы ΠΎΡ‚ Β«ΡΡŽΡ€ΠΏΡ€ΠΈΠ·ΠΎΠ²Β».

ΠšΠΎΠ²Π°Ρ€ΠΈΠ°Π½Ρ‚Π½ΠΎΡΡ‚ΡŒ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ²

Π’ Java SE5 появилась концСпция ковариантности Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ²; этот Ρ‚Π΅Ρ€ΠΌΠΈΠ½ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½ΠΎΠ³ΠΎ класса ΠΌΠΎΠΆΠ΅Ρ‚ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ Ρ‚ΠΈΠΏ, ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½Ρ‹ΠΉ ΠΎΡ‚ Ρ‚ΠΈΠΏΠ°, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ класса:

//: polymorph!sm/CovanantReturn java

class Grain {

public String toStringO { return "Grain"; }

}

class Wheat extends Grain {

public String toStringO { return "Wheat"; }

class Mill {

Grain process О { return new GrainO; }

}

class WheatMill extends Mill {

Wheat process О { return new WheatO; }

}

public class CovariantReturn {

public static void main(String[] args) { Mill m = new Mi 11(); Grain g = m.processO; System out println(g); m = new WheatMi 110; g = m process О, System out.println(g);

}

} /* Output Grain Wheat */// ~

Π“Π»Π°Π²Π½ΠΎΠ΅ ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ Java SE5 ΠΎΡ‚ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΡ… вСрсий Java Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ старыС вСрсии заставляли ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ process() Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ Grain вмСсто Wheat, хотя Ρ‚ΠΈΠΏ Wheat, ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½Ρ‹ΠΉ ΠΎΡ‚ Grain, являСтся допустимым Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹ΠΌ Ρ‚ΠΈΠΏΠΎΠΌ. ΠšΠΎΠ²Π°Ρ€ΠΈΠ°Π½Ρ‚Π½ΠΎΡΡ‚ΡŒ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ² позволяСт Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ Π±ΠΎΠ»Π΅Π΅ спСциализированный Ρ‚ΠΈΠΏ Wheat.

Π Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° с наслСдованиСм

ПослС знакомства с ΠΏΠΎΠ»ΠΈΠΌΠΎΡ€Ρ„ΠΈΠ·ΠΌΠΎΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ, Ρ‡Ρ‚ΠΎ Π΅Π³ΠΎ слСдуСт ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ Π²Π΅Π·Π΄Π΅ ΠΈ всСгда. Однако Π·Π»ΠΎΡƒΠΏΠΎΡ‚Ρ€Π΅Π±Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ»ΠΈΠΌΠΎΡ€Ρ„ΠΈΠ·ΠΌΠΎΠΌ ΡƒΡ…ΡƒΠ΄ΡˆΠΈΡ‚ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ Π²Π°ΡˆΠΈΡ… ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ.

Π›ΡƒΡ‡ΡˆΠ΅ для Π½Π°Ρ‡Π°Π»Π° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΡŽ, ΠΏΠΎΠΊΠ° Π²Ρ‹ Ρ‚ΠΎΡ‡Π½ΠΎ Π½Π΅ ΡƒΠ²Π΅Ρ€Π΅Π½Ρ‹ Π² Ρ‚ΠΎΠΌ, ΠΊΠ°ΠΊΠΎΠΉ ΠΈΠΌΠ΅Π½Π½ΠΎ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ слСдуСт Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ. ΠšΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΡ Π½Π΅ стСсняСт Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ Ρ€Π°ΠΌΠΊΠ°ΠΌΠΈ ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΠΈ наслСдования. К Ρ‚ΠΎΠΌΡƒ ΠΆΠ΅ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ Π±ΠΎΠ»Π΅Π΅ Π³ΠΈΠ±ΠΎΠΊ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΎΠ½ позволяСт динамичСски Π²Ρ‹Π±ΠΈΡ€Π°Ρ‚ΡŒ Ρ‚ΠΈΠΏ (Π° ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, ΠΈ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅), Ρ‚ΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ наслСдованиС Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ‚ΠΎΡ‡Π½Ρ‹ΠΉ Ρ‚ΠΈΠΏ Π±Ρ‹Π» извСстСн ΡƒΠΆΠ΅ Π²ΠΎ врСмя компиляции. Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ дСмонстрируСт это:

// polymorphi sm/Transmogrify.java // ДинамичСскоС ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ повСдСния ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° // с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ (шаблон проСктирования «БостояниС») β€’ import static net.mindview.util.Print.*;

class Actor {

public void act О {}

}

class HappyActor extends Actor {

public void actO { pri nt ("HappyActor"), }

class SadActor extends Actor {

public void act() { printCSadActor"). }

}

class Stage {

private Actor actor = new HappyActor(); public void changeO { actor = new SadActorO. } public void performPlayO { actor.act(), }

}

public class Transmogrify {

public static void main(String[] args) { Stage stage = new StageO; stage. performPlayO; stage. changeO; stage. performPlayO;

}

} /* Output-

HappyActor

SadActor

*///:-

ΠžΠ±ΡŠΠ΅ΠΊΡ‚ Stage содСрТит ссылку Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Actor, которая инициализируСтся ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠΌ HappyActor. Π­Ρ‚ΠΎ Π·Π½Π°Ρ‡ΠΈΡ‚, Ρ‡Ρ‚ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄ performPlayO ΠΈΠΌΠ΅Π΅Ρ‚ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅. Но Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ссылку Π½Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π½ΠΎΠ²ΠΎ ΠΏΡ€ΠΈΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ ΠΊ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρƒ Π²ΠΎ врСмя выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, ссылкС actor назначаСтся ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ SadActor, ΠΈ послС этого ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° performPlayO измСняСтся. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΡƒΠ»ΡƒΡ‡ΡˆΠ°Π΅Ρ‚ΡΡ Π΄ΠΈΠ½Π°ΠΌΠΈΠΊΠ° повСдСния Π½Π° стадии выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. Π‘ Π΄Ρ€ΡƒΠ³ΠΎΠΉ стороны, ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒΡΡ Π½Π° Π΄Ρ€ΡƒΠ³ΠΎΠΉ способ наслСдования Π²ΠΎ врСмя Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ; иСрархия наслСдования Ρ€Π°Π· ΠΈ навсСгда опрСдСляСтся Π² процСссС компиляции ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹.

НисходящСС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈ динамичСскоС ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠΎΠ²

Π’Π°ΠΊ ΠΊΠ°ΠΊ ΠΏΡ€ΠΈ ΠΏΡ€ΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠΈ восходящСго прСобразования (ΠΏΠ΅Ρ€Π΅Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ Π²Π²Π΅Ρ€Ρ… ΠΏΠΎ ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΠΈ наслСдования) тСряСтся информация, характСрная для ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ°, Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ СстСствСнноС ΠΆΠ΅Π»Π°Π½ΠΈΠ΅ Π²ΠΎΡΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π΅Π΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ нисходящСго прСобразования. Π’ΠΏΡ€ΠΎΡ‡Π΅ΠΌ, ΠΌΡ‹ Π·Π½Π°Π΅ΠΌ, Ρ‡Ρ‚ΠΎ восходящСС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Π°Π±ΡΠΎΠ»ΡŽΡ‚Π½ΠΎ бСзопасно; Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ класс Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ «больший» интСрфСйс, Ρ‡Π΅ΠΌ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½Ρ‹ΠΉ класс, ΠΈ поэтому любоС сообщСниС, посланноС Π±Π°Π·ΠΎΠ²ΠΎΠΌΡƒ классу, Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎ Π΄ΠΎΠΉΠ΄Π΅Ρ‚ Π΄ΠΎ получатСля. Но ΠΏΡ€ΠΈ использовании нисходящСго прСобразования Π²Ρ‹ Π½Π΅ Π·Π½Π°Π΅Ρ‚Π΅ достовСрно, Ρ‡Ρ‚ΠΎ Ρ„ΠΈΠ³ΡƒΡ€Π° (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€) Π² Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ являСтся ΠΎΠΊΡ€ΡƒΠΆΠ½ΠΎΡΡ‚ΡŒΡŽ. Π‘ Ρ‚Π°ΠΊΠΎΠΉ ΠΆΠ΅ Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒΡŽ ΠΎΠ½Π° ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ Ρ‚Ρ€Π΅ΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊΠΎΠΌ, ΠΏΡ€ΡΠΌΠΎΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΈΠΊΠΎΠΌ ΠΈΠ»ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠΌ Ρ‚ΠΈΠΏΠΎΠΌ.

Π”ΠΎΠ»ΠΆΠ΅Π½ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠ°ΠΊΠΎΠΉ-Ρ‚ΠΎ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ, Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΡΡ‚ΡŒ нисходящСго прСобразования; Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ случайно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π½Π΅Π²Π΅Ρ€Π½Ρ‹ΠΉ Ρ‚ΠΈΠΏ, послав Π΅ΠΌΡƒ сообщСниС, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΎΠ½ Π½Π΅ Π² состоянии ΠΏΡ€ΠΈΠ½ΡΡ‚ΡŒ. Π­Ρ‚ΠΎ Π±Ρ‹Π»ΠΎ Π±Ρ‹ нСбСзопасно.

Π’ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… языках (ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹Ρ… Π‘++) для провСдСния бСзопасного нисходящСго прСобразования Ρ‚ΠΈΠΏΠΎΠ² Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ провСсти ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Π½ΠΎ Π² Java ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ контролируСтся! ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ, хотя внСшнС всС выглядит ΠΊΠ°ΠΊ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ΅ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠΎΠ² Π² ΠΊΡ€ΡƒΠ³Π»Ρ‹Ρ… скобках, Π²ΠΎ врСмя выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ это ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΡ€ΠΎΡ…ΠΎΠ΄ΠΈΡ‚ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ Π½Π° фактичСскоС соотвСтствиС Ρ‚ΠΈΠΏΡƒ. Если Ρ‚ΠΈΠΏΡ‹ Π½Π΅ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‚, происходит ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ClassCastException. ΠŸΡ€ΠΎΡ†Π΅ΡΡ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Ρ‚ΠΈΠΏΠΎΠ² Π²ΠΎ врСмя выполнСния ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ называСтся динамичСским ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ΠΌ Ρ‚ΠΈΠΏΠΎΠ² (run-time type identification, RTTI). Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ дСмонстрируСт дСйствиС RTTI:

//: polymorphi sm/RTTI java

// НисходящСС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈ динамичСскоС ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Ρ‚ΠΈΠΏΠΎΠ² (RTTI)

// {ThrowException}

class Useful {

public void f() {} public void g() {}

}

class MoreUseful extends Useful { public void f() {} public void g() {} public void u() {} public void v() {} public void w() {}

}

public class RTTI {

public static void main(String[] args) { Useful[] x = {

new Useful О. new MoreUsefulО

}:

x[0].f(): x[l] g().

// БВадия компиляции- ΠΌΠ΅Ρ‚ΠΎΠ΄ Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½ Π² классС Usefulβ€’ //! x[l].u().

((MoreUseful)Ρ…[1]) u(); // Нисх ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ /RTTI ((MoreUseful)x[0]).u0; // ΠŸΡ€ΠΎΠΈΡΡ…ΠΎΠ΄ΠΈΡ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

}

} ///:-

Класс MoreUseful Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅Ρ‚ интСрфСйс класса Useful. Но благодаря наслСдованию ΠΎΠ½ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ ΠΊ Ρ‚ΠΈΠΏΡƒ Useful. Π’Ρ‹ Π²ΠΈΠ΄ΠΈΡ‚Π΅, ΠΊΠ°ΠΊ это происходит, ΠΏΡ€ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ массива Ρ… Π² ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ main(). Π’Π°ΠΊ ΠΊΠ°ΠΊ ΠΎΠ±Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° Π² массивС ΡΠ²Π»ΡΡŽΡ‚ΡΡ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½Ρ‹ΠΌΠΈ ΠΎΡ‚ Useful, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠΎΡΠ»Π°Ρ‚ΡŒ сообщСния (Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹) f() ΠΈ Π΄() для ΠΎΠ±ΠΎΠΈΡ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ², Π½ΠΎ ΠΏΡ€ΠΈ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ΅ Π²Ρ‹Π·ΠΎΠ²Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ΠΈ() (ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ сущСствуСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² классС MoreUseful) Π²Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ сообщСниС ΠΎΠ± ошибкС компиляции.

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΊ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½Π½ΠΎΠΌΡƒ интСрфСйсу ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° MoreUseful, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ нисходящСС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅. Если Ρ‚ΠΈΠΏ ΡƒΠΊΠ°Π·Π°Π½ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ, всС ΠΏΡ€ΠΎΠΉΠ΄Π΅Ρ‚ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ; ΠΈΠ½Π°Ρ‡Π΅ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ClassCastException. Π’Π°ΠΌ Π½Π΅ понадобится ΠΏΠΈΡΠ°Ρ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠΎΠ΄ для этого ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ½ΠΎ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° ΠΎΠ±Ρ‰ΡƒΡŽ ΠΎΡˆΠΈΠ±ΠΊΡƒ, которая ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΡ‚ΠΈ Π² любом мСстС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹.