ලිස්කොව් ආදේශන මූලධර්මයේ උදාහරණයක් කුමක්ද?


933

ලිස්කොව් ආදේශන මූලධර්මය (එල්එස්පී) වස්තු නැඹුරු නිර්මාණයේ මූලික මූලධර්මයක් බව මම අසා ඇත්තෙමි. එය කුමක්ද සහ එහි භාවිතය පිළිබඳ උදාහරණ මොනවාද?


එල්එස්පී පිළිපැදීම සහ
උල්ලං violation නය

1
මෙම ප්‍රශ්නයට අසීමිත තරම් හොඳ පිළිතුරු ඇති අතර එය ඉතා පුළුල් ය .
රයිඩ්වෝල්ඩ්

Answers:


922

එල්එස්පී (බොබ් මාමා විසින් මෑතකදී මා අසා ඇති පොඩ්කාස්ට් එකකින් ලබා දුන්) නිදර්ශනය කරන විශිෂ්ට උදාහරණයක් නම්, සමහර විට ස්වාභාවික භාෂාවෙන් නිවැරදි යැයි පෙනෙන දෙයක් කේතයෙන් ක්‍රියා නොකරන්නේ කෙසේද යන්නයි.

ගණිතයේ a Squareයනු a Rectangle. ඇත්ත වශයෙන්ම එය සෘජුකෝණාස්රයේ විශේෂීකරණයකි. "යනු" ඔබට මෙය උරුමය සමඟ ආදර්ශනය කිරීමට අවශ්‍ය කරයි. කෙසේ වෙතත් ඔබ සෑදූ කේතයෙන් Squareව්‍යුත්පන්න වී ඇත්නම් Rectangle, Squareඔබ අපේක්ෂා කරන ඕනෑම තැනක භාවිතා කළ හැකි විය යුතුය Rectangle. මෙය යම් අමුතු හැසිරීමක් ඇති කරයි.

ඔබේ මූලික පන්තියේ ඔබට ඇති ක්‍රම SetWidthසහ SetHeightක්‍රම ගැන සිතන්න Rectangle; මෙය සම්පූර්ණයෙන්ම තර්කානුකූල බව පෙනේ. ඔබගේ නම් කෙසේ වෙතත් Rectangleඅදාල නම් පෙන්වා Square, පසුව SetWidthහා SetHeightහැඟීමක් එක් එය ගැලපෙන අනෙක් වෙනස් කිරීමට ඉඩ ඇත සැකසීම නිසා කරන්නේ නැහැ. මෙම අවස්ථාවේ Squareදී ලිස්කොව් ආදේශන පරීක්ෂණය අසමත් Rectangleවන අතර එයින් Squareඋරුමයක් ලබා Rectangleගැනීම වියුක්ත කිරීම නරක දෙයකි.

රූප විස්තරය මෙහි ඇතුළත් කරන්න

අනෙක් මිල කළ නොහැකි SOLID මූලධර්ම අභිප්‍රේරණ පෝස්ටර් පරීක්ෂා කළ යුතුය .


20
@ m-sharp එය SetWidth සහ SetHeight වෙනුවට වෙනස් කළ නොහැකි සෘජුකෝණාස්රයක් නම්, අපට GetWidth සහ GetHeight ක්‍රම තිබේ.
පැසීරියර්

145
කතාවේ සදාචාරය: දේපල මත නොව හැසිරීම් මත පදනම්ව ඔබේ පන්ති ආදර්ශනය කරන්න; හැසිරීම් මත නොව ගුණාංග මත පදනම්ව ඔබේ දත්ත ආදර්ශනය කරන්න. එය තාරාවෙකු මෙන් හැසිරෙන්නේ නම්, එය නිසැකවම කුරුල්ලෙකි.
ස්කලිව්ස්

201
හොඳයි, චතුරස්රයක් යනු සැබෑ ලෝකයේ සෘජුකෝණාස්රයකි. අපගේ කේතයෙන් අපට මෙය ආදර්ශනය කළ හැකිද යන්න පිරිවිතර මත රඳා පවතී. එල්එස්පී ඇඟවුම් කරන්නේ උප වර්ගයේ හැසිරීම මූලික වර්ගයේ පිරිවිතරයන්ට අනුව මූලික වර්ගයේ හැසිරීමට අනුරූප විය යුතු බවයි. උස හා පළල ස්වාධීනව සැකසිය හැකි බව සෘජුකෝණාස්රාකාර පාදක පිරිවිතරයේ සඳහන් කරන්නේ නම්, එල්එස්පී පවසන්නේ චතුරස්රය සෘජුකෝණාස්රයේ උප වර්ගයක් විය නොහැකි බවයි. සෘජුකෝණාස්රය නිශ්චල නොවන බව සෘජුකෝණාස්රාකාර පිරිවිතරයන් පවසන්නේ නම්, චතුරස්රයක් සෘජුකෝණාස්රයේ උප වර්ගයක් විය හැකිය. මේ සියල්ලම මූලික වර්ගය සඳහා නිශ්චිතව දක්වා ඇති හැසිරීම පවත්වා ගෙන යන උප ප්‍රභේදයන් වේ.
ස්ටීව්ට්

64
පැකේරියර් එය වෙනස් කළ නොහැකි නම් ගැටලුවක් නොමැත. මෙහි ඇති සැබෑ ගැටළුව නම්, අපි ආකෘති සෘජුකෝණාස්රා නොව, “නැවත සකස් කළ හැකි සෘජුකෝණාස්රා”, එනම්, නිර්මාණයෙන් පසු පළල හෝ උස වෙනස් කළ හැකි සෘජුකෝණාස්රා (අපි තවමත් එය එකම වස්තුවක් ලෙස සලකමු). අප මේ ආකාරයෙන් සෘජුකෝණාස්රා පන්තිය දෙස බැලුවහොත්, චතුරස්රයක් "නැවත සකස් කළ හැකි සෘජුකෝණාස්රයක්" නොවන බව පැහැදිලිය, මන්ද යත්, චතුරස්රයක් නැවත සකස් කළ නොහැකි අතර තවමත් චතුරස්රයක් (පොදුවේ) විය හැකිය. ගණිතමය වශයෙන්, අපට ගැටලුව නොපෙනෙන්නේ විකෘතිතාව ගණිතමය සන්දර්භයක් තුළ පවා අර්ථවත් නොවන බැවිනි.
asmeurer

14
මූලධර්මය ගැන මට එක ප්‍රශ්නයක් තිබේ. නම් ඇයි ප්රශ්නය වනු ඇත Square.setWidth(int width)මේ වගේ ක්රියාත්මක කරන ලදී: this.width = width; this.height = width;? මෙම අවස්ථාවේ දී පළල උස සමාන බව සහතික කෙරේ.
එම්සී අධිරාජ්‍යයා

496

ලිස්කොව් ආදේශන මූලධර්මය (එල්එස්පී, ) යනු වස්තු දිශානතිගත ක්‍රමලේඛනයේ සංකල්පයකි:

පාදක පංති වෙත යොමු කිරීම් හෝ යොමු කිරීම් භාවිතා කරන කාර්යයන් නොදැන ව්‍යුත්පන්න පංතිවල වස්තු භාවිතා කළ යුතුය.

එල්එස්පී එහි හදවතේ අතුරුමුහුණත් සහ කොන්ත්‍රාත්තු මෙන්ම පන්තියක් එදිරිව දීර් extend කළ යුත්තේ කවදාද යන්න තීරණය කරන්නේ කෙසේද යන්න පිළිබඳව ඔබේ ඉලක්කය සපුරා ගැනීම සඳහා සංයුතිය වැනි තවත් උපාය මාර්ගයක් භාවිතා කරන්න.

මෙම කරුණ නිදර්ශනය කිරීම සඳහා මා දුටු වඩාත් way ලදායී ක්‍රමය වූයේ හෙඩ් ෆස්ට් ඕඕඒ සහ ඩී . උපාය මාර්ගික ක්‍රීඩා සඳහා රාමුවක් ගොඩනැගීම සඳහා ඔබ ව්‍යාපෘතියක සංවර්ධකයෙකු වන අවස්ථාවක් ඔවුන් ඉදිරිපත් කරයි.

ඔවුන් මේ ආකාරයට පෙනෙන පුවරුවක් නියෝජනය කරන පන්තියක් ඉදිරිපත් කරයි:

පන්ති රූප සටහන

ද්විමාන අරාවෙහි උළු පිහිටීම සොයා ගැනීම සඳහා සියලු ක්‍රම X සහ Y ඛණ්ඩාංක පරාමිතීන් ලෙස ගනී Tiles. මෙමඟින් ක්‍රීඩා සංවර්ධකයෙකුට ක්‍රීඩාව අතරතුර පුවරුවේ ඒකක කළමනාකරණය කිරීමට ඉඩ දෙනු ඇත.

පියාසර කරන ක්‍රීඩා සඳහා ඉඩ සැලසීමට ක්‍රීඩා රාමු වැඩ ත්‍රිමාණ ක්‍රීඩා පුවරුවලට සහාය විය යුතු බව පැවසීමට අවශ්‍යතාවයන් පොත වෙනස් කරයි. එබැවින් ThreeDBoardපන්තියක් හඳුන්වා දෙනු Boardලැබේ.

බැලූ බැල්මට මෙය හොඳ තීරණයක් සේ පෙනේ. සහ ගුණාංග Boardදෙකම සපයන අතර Z අක්ෂය සපයයි.HeightWidthThreeDBoard

එය බිඳ වැටෙන ස්ථානය වන්නේ ඔබ උරුම කර ගත් අනෙක් සියලුම සාමාජිකයන් දෙස බැලීමයි Board. සඳහා ක්රම AddUnit, GetTile, GetUnits, එසේ සියලු තුළ X හා Y පරාමිතීන් දෙක ගත Boardපන්ති නමුත් ThreeDBoardලෙස හොඳින් Z පරාමිතිය අවශ්ය වේ.

එබැවින් ඔබ නැවත Z පරාමිතියක් සමඟ එම ක්‍රම ක්‍රියාත්මක කළ යුතුය. ඉසෙඩ් පරාමිතියට Boardපන්තියට සන්දර්භයක් නොමැති අතර පන්තියෙන් උරුම වූ ක්‍රමවල Boardඅර්ථය නැති වී යයි. කේත ඒකකයක් ThreeDBoardපන්තිය එහි මූලික පන්තිය ලෙස භාවිතා කිරීමට උත්සාහ Boardකිරීම වාසනාවකි.

සමහර විට අපි වෙනත් ප්‍රවේශයක් සොයා ගත යුතුයි. දීර්ඝ වෙනුවට Board, ThreeDBoardසමන්විත විය යුතුය Boardවස්තූන්. Boardඉසෙඩ් අක්ෂයේ ඒකකයකට එක් වස්තුවක්.

සංවෘත කිරීම සහ නැවත භාවිතා කිරීම වැනි හොඳ වස්තු නැඹුරු මූලධර්ම භාවිතා කිරීමට මෙය අපට ඉඩ සලසයි.


10
මෙයද බලන්න කවය-Ellipse ගැටළු හා සමාන නමුත් සරල උදාහරණයක් විකිපීඩියා, නිදහස් විශ්වකෝෂය පිළිබඳ.
බ්‍රයන්

OtNotMySelf වෙතින් ඉල්ලීම: "උදාහරණය වන්නේ ත්‍රි ඩී බෝඩ් හි සන්දර්භය තුළ පුවරුවෙන් උරුම වීම අර්ථවත් නොවන බව නිරූපණය කිරීම පමණක් වන අතර සියලුම අත්සන ඉසෙඩ් අක්ෂයකින් අර්ථ විරහිත ය."
කොන්ටැන්ගෝ

1
ඉතින් අපි ළමා පන්තියකට තවත් ක්‍රමයක් එකතු කළත්, දෙමව්පියන්ගේ සියලු ක්‍රියාකාරිත්වය තවමත් ළමා පන්තියේ අර්ථවත් වන්නේ නම් එය එල්එස්පී බිඳ දැමීමක් ද? එක් අතකින් අපි දරුවා මවුපියන් බවට පත් කළහොත් අනෙක් අතට දරුවා භාවිතා කිරීම සඳහා අතුරු මුහුණත වෙනස් කළෙමු. දෙමව්පියන් බලාපොරොත්තු වන කේතය හොඳින් ක්‍රියාත්මක වේ.
නිකොලායි කොන්ඩ්‍රැටෙව්

5
මෙය ලිස්කොව් විරෝධී උදාහරණයකි. ලිස්කොව් අපව චතුරස්රයෙන් සෘජුකෝණාස්රය ව්‍යුත්පන්න කරයි. අඩු-පරාමිති-පන්තියේ සිට වැඩි-පරාමිති-පන්තිය. එය නරක බව ඔබ මනාව පෙන්වා ඇත. පිළිතුරක් ලෙස සලකුණු කිරීම සහ ලිස්කොව් ප්‍රශ්නයට ලිස්කොව් විරෝධී පිළිතුරක් 200 ගුණයක් ඉහළට ඔසවා තැබීම ඇත්තෙන්ම හොඳ විහිළුවකි. ලිස්කොව් මූලධර්මය ඇත්ත වශයෙන්ම වැරදිද?
ගන්ග්නස්

3
උරුමය වැරදි ආකාරයකින් කරන බව මම දැක ඇත්තෙමි. මෙන්න උදාහරණයක්. මූලික පන්තිය 3DBoard සහ ව්‍යුත්පන්න පන්ති මණ්ඩලය විය යුතුය. මණ්ඩලයට තවමත් මැක්ස් (ඉසෙඩ්) = අවම (ඉසෙඩ්) = 1 හි ඉසෙඩ් අක්ෂයක් ඇත
පෝල්ස්ට්‍රියස්

178

ආදේශකතාව යනු වස්තු-නැඹුරු වැඩසටහන්කරණයේ මූලධර්මයක් වන අතර, පරිගණක වැඩසටහනක S යනු T හි උප ප්‍රභේදයක් නම්, T වර්ගයේ වස්තු S වර්ගයේ වස්තූන් සමඟ ප්‍රතිස්ථාපනය කළ හැකිය.

ජාවා හි සරල උදාහරණයක් කරමු:

නරක උදාහරණය

public class Bird{
    public void fly(){}
}
public class Duck extends Bird{}

කුරුල්ලෙකු නිසා තාරාවාට පියාසර කළ හැකිය, නමුත් මේ ගැන කුමක් කිව හැකිද:

public class Ostrich extends Bird{}

පැස්බරා කුරුල්ලෙකි, නමුත් එයට පියාසර කළ නොහැක, පැස්බරා පන්තිය කුරුල්ලන්ගේ උප ප්‍රභේදයකි, නමුත් එයට පියාසර ක්‍රමය භාවිතා කළ නොහැක, එයින් අදහස් වන්නේ අප එල්එස්පී මූලධර්මය කඩ කරන බවයි.

හොඳ උදාහරණයක්

public class Bird{
}
public class FlyingBirds extends Bird{
    public void fly(){}
}
public class Duck extends FlyingBirds{}
public class Ostrich extends Bird{} 

5
ලස්සන උදාහරණයක් ලෙස, නමුත් සේවාදායකයෙක් නම්, ඔබ කුමක් කළ බව Bird bird. මැස්සන් භාවිතා කිරීම සඳහා ඔබ වස්තුව ෆ්ලයිංබර්ඩ්ස් වෙත දැමිය යුතුය, එය හරිද?
මූඩි

20
සේවාදායකයාට තිබේ නම් Bird bird, එයින් අදහස් වන්නේ එය භාවිතා කළ නොහැකි fly()බවයි. ඒක තමයි. සම්මත Duckවීමෙන් මෙම කාරණය වෙනස් නොවේ. සේවාදායකයාට තිබේ FlyingBirds birdනම්, එය සමත් වුව ද එය Duckසෑම විටම එකම ආකාරයකින් ක්‍රියා කළ යුතුය.
ස්ටීව් චමයිලාර්ඩ්

12
මෙය අතුරු මුහුණත් වෙන් කිරීම සඳහා හොඳ උදාහරණයක් ද නොවේද?
සහර්ෂ්

1
විශිෂ්ට උදාහරණය ස්තූතියි මිනිසා
අබ්දෙල්හාඩි අබ්ඩෝ

6
'පියාසර කළ හැකි' අතුරුමුහුණත භාවිතා කරන්නේ කෙසේද (වඩා හොඳ නමක් ගැන සිතිය නොහැක). මේ ආකාරයෙන් අපි මෙම දෘඩ ධූරාවලියට බැඳී නොසිටිමු .. අප නොදන්නේ නම් එය සැබවින්ම අවශ්‍ය වේ.
තෙවන

135

එල්එස්පී ආක්‍රමණ ගැන සැලකිලිමත් වේ.

සම්භාව්‍ය උදාහරණය පහත දැක්වෙන ව්‍යාජ කේත ප්‍රකාශනය මගින් ලබා දී ඇත (ක්‍රියාත්මක කිරීම් මඟ හැරී ඇත):

class Rectangle {
    int getHeight()
    void setHeight(int value)
    int getWidth()
    void setWidth(int value)
}

class Square : Rectangle { }

අතුරුමුහුණත ගැලපුණද දැන් අපට ගැටලුවක් තිබේ. හේතුව, අපි චතුරස්රයන් සහ සෘජුකෝණාස්රා වල ගණිතමය අර්ථ දැක්වීමෙන් පැනනැඟී ඇති වෙනස්වීම් උල්ලං have නය කර තිබීමයි. ලබා ගන්නන් සහ සැකසීම් ක්‍රියා කරන ආකාරය, Rectangleපහත සඳහන් වෙනස්වීම් සපුරාලිය යුතුය:

void invariant(Rectangle r) {
    r.setHeight(200)
    r.setWidth(100)
    assert(r.getHeight() == 200 and r.getWidth() == 100)
}

කෙසේ වෙතත්, මෙම වෙනස් කිරීම නිවැරදිව ක්‍රියාත්මක කිරීම මගින් උල්ලං must නය කළ යුතුය Square, එබැවින් එය වලංගු ආදේශකයක් නොවේ Rectangle.


36
එබැවින් අපට ඇත්ත වශයෙන්ම ආදර්ශනය කිරීමට අවශ්‍ය ඕනෑම දෙයක් ආදර්ශනය කිරීමට "OO" භාවිතා කිරීමේ දුෂ්කරතාවය.
DrPizza

10
RDrPizza: නිසැකවම. කෙසේ වෙතත්, කරුණු දෙකක්. පළමුවෙන්ම, එවැනි සබඳතා තවමත් OOP හි ආදර්ශනය කළ හැකිය, අසම්පූර්ණ වුවද හෝ වඩාත් සංකීර්ණ මාරුවීම් භාවිතා කළ හැකිය (ඔබේ ගැටලුවට ගැලපෙන දේ තෝරන්න). දෙවනුව, වඩා හොඳ විකල්පයක් නැත. වෙනත් සිතියම්කරණය / ආකෘතිකරණයට සමාන හෝ සමාන ගැටළු ඇත. ;-)
කොන්රාඩ් රුඩොල්ෆ්

7
IckNickW සමහර අවස්ථාවලදී (නමුත් ඉහත නොවේ) ඔබට සරලවම උරුම දාමය පෙරළා දැමිය හැකිය - තර්කානුකූලව කිවහොත්, 2D ලක්ෂ්‍යයක් යනු ත්‍රිමාණ ලක්ෂ්‍යයකි, එහිදී තුන්වන මානය නොසලකා හරිනු ලැබේ (හෝ 0 - සියලුම ලක්ෂ්‍ය එකම තලයක පිහිටා ඇත 3D අවකාශය). නමුත් මෙය ඇත්ත වශයෙන්ම ප්‍රායෝගික නොවේ. පොදුවේ ගත් කල, මෙය උරුමය සැබවින්ම උදව් නොකරන එක් අවස්ථාවක් වන අතර, ආයතන අතර ස්වාභාවික සම්බන්ධතාවයක් නොමැත. ඒවා වෙන වෙනම ආදර්ශනය කරන්න (අවම වශයෙන් වඩා හොඳ ක්‍රමයක් ගැන මම නොදනිමි).
කොන්රාඩ් රුඩොල්ෆ්

7
OOP යන්නෙන් අදහස් කරන්නේ ආදර්ශ හැසිරීම් මිස දත්ත නොවේ. එල්එස්පී උල්ලං before නය කිරීමට පෙර පවා ඔබේ පන්ති සංසරණය උල්ලං late නය කරයි.
ස්කලිව්ස්

2
Ust ඔස්ටින් ඩබ්ලිව් බ්‍රයන් යෙප්; මම මෙම ක්‍ෂේත්‍රයේ වැඩි කාලයක් වැඩ කර ඇති තරමට, මම අතුරු මුහුණත් සහ වියුක්ත පාදක පන්ති සඳහා පමණක් උරුමය භාවිතා කිරීමට නැඹුරු වෙමි. එය සමහර විට තව ටිකක් වැඩකි (යතුරු ලියනය නැණවත්) නමුත් එය සමස්ත ගැටලු රාශියක් මගහරින අතර අනෙකුත් පළපුරුදු ක්‍රමලේඛකයින්ගේ උපදෙස් දෝංකාර දෙයි.
කොන්රාඩ් රුඩොල්ෆ්

78

රොබට් මාටින් ලිස්කොව් ආදේශන මූලධර්මය පිළිබඳ විශිෂ්ට ලිපියක් ඇත . මූලධර්මය උල්ලං may නය විය හැකි සියුම් හා එතරම් සියුම් නොවන ආකාරයන් මෙහි සාකච්ඡා කරයි.

පුවත්පතේ අදාළ සමහර කොටස් (දෙවන උදාහරණය දැඩි ලෙස ensed නීභවනය වී ඇති බව සලකන්න):

එල්එස්පී උල්ලං lation නය කිරීම පිළිබඳ සරල උදාහරණයක්

මෙම මූලධර්මයේ වඩාත්ම පැහැදිලිව උල්ලං lations නය කිරීම්වලින් එකක් වන්නේ වස්තුවක වර්ගය මත පදනම්ව ශ්‍රිතයක් තෝරා ගැනීම සඳහා C ++ ධාවන කාල තොරතුරු තොරතුරු (RTTI) භාවිතා කිරීමයි. එනම්:

void DrawShape(const Shape& s)
{
  if (typeid(s) == typeid(Square))
    DrawSquare(static_cast<Square&>(s)); 
  else if (typeid(s) == typeid(Circle))
    DrawCircle(static_cast<Circle&>(s));
}

පැහැදිලිවම DrawShapeකාර්යය නරක ලෙස පිහිටුවා ඇත. Shapeපංතියේ විය හැකි සෑම ව්‍යුත්පන්නයක් ගැනම එය දැන සිටිය යුතු අතර, නව ව්‍යුත්පන්නයන් Shapeනිර්මාණය කරන සෑම විටම එය වෙනස් කළ යුතුය . ඇත්ත වශයෙන්ම, බොහෝ දෙනෙක් මෙම ශ්‍රිතයේ ව්‍යුහය වස්තු දිශානත නිර්මාණයට පිළිකුලක් ලෙස සලකති.

චතුරස්රය සහ සෘජුකෝණාස්රය, වඩාත් සියුම් උල්ලං .නය කිරීමකි.

කෙසේ වෙතත්, එල්එස්පී උල්ලං ting නය කිරීමේ වෙනත්, ඊටත් වඩා සියුම් ක්‍රම තිබේ. Rectangleපහත විස්තර කර ඇති පරිදි පන්තිය භාවිතා කරන යෙදුමක් සලකා බලන්න :

class Rectangle
{
  public:
    void SetWidth(double w) {itsWidth=w;}
    void SetHeight(double h) {itsHeight=w;}
    double GetHeight() const {return itsHeight;}
    double GetWidth() const {return itsWidth;}
  private:
    double itsWidth;
    double itsHeight;
};

[...] එක් දිනක් පරිශීලකයින් සෘජුකෝණාස්රා වලට අමතරව චතුරස්රයන් හැසිරවීමේ හැකියාව ඉල්ලා සිටින බව සිතන්න. [...]

පැහැදිලිවම, චතුරස්රයක් යනු සියලු සාමාන්ය අභිප්රායන් සහ අරමුණු සඳහා සෘජුකෝණාස්රයකි. අයිඑස්ඒ සම්බන්ධතාවය පවතින බැවින්, Square පන්තිය ව්‍යුත්පන්න වූවක් ලෙස ආදර්ශනය කිරීම තර්කානුකූල ය Rectangle. [...]

SquareSetWidthසහ SetHeightකාර්යයන් උරුම කර දෙනු ඇත . Squareවර්ගයක පළල සහ උස සමාන බැවින් මෙම කාර්යයන් a සඳහා සම්පූර්ණයෙන්ම නුසුදුසු ය . සැලසුමේ ගැටලුවක් ඇති බවට මෙය සැලකිය යුතු හෝඩුවාවක් විය යුතුය. කෙසේ වෙතත්, ගැටළුව මඟ හැරීමට ක්රමයක් තිබේ. අපට අභිබවා යා හැකි SetWidthඅතර SetHeight[...]

නමුත් පහත සඳහන් කාර්යය සලකා බලන්න:

void f(Rectangle& r)
{
  r.SetWidth(32); // calls Rectangle::SetWidth
}

Squareමෙම ශ්‍රිතයට අප යම් වස්තුවක් වෙත යොමු කිරීමක් කළහොත් Square, උස වෙනස් නොවන නිසා වස්තුව දූෂිත වේ. මෙය පැහැදිලිවම එල්එස්පී උල්ලං is නය කිරීමකි. ශ්‍රිතය එහි තර්කවල ව්‍යුත්පන්නයන් සඳහා ක්‍රියා නොකරයි.

[...]


15
ප්‍රමාද වී ඇති නමුත් මම සිතුවේ මෙය එම ලිපියේ සිත්ගන්නාසුලු උපුටා දැක්වීමක් බවයි: Now the rule for the preconditions and postconditions for derivatives, as stated by Meyer is: ...when redefining a routine [in a derivative], you may only replace its precondition by a weaker one, and its postcondition by a stronger one. ළමා පන්තියේ පූර්ව කොන්දේසිය දෙමාපිය පන්තියේ පූර්ව කොන්දේසියට වඩා ශක්තිමත් නම්, ඔබට පූර්ව කොන්දේසිය උල්ලං without නය නොකර දෙමව්පියන්ට දරුවෙකු ආදේශ කළ නොහැක. එබැවින් එල්එස්පී.
user2023861

@ user2023861 ඔබ හරි. මම මේ මත පදනම්ව පිළිතුරක් ලියමි.
inf3rno

41

සමහර කේතයන් එය වර්ගයක ක්‍රමවේදයන් යැයි සිතන තැන LSP අවශ්‍ය වන අතර T, නොදැනුවත්වම වර්ගයක ක්‍රමවේදයන් හැඳින්විය හැකිය S, එහිදී S extends T(එනම්, Sඋරුම, ව්‍යුත්පන්න හෝ සුපිරි ප්‍රභේදයේ උප ප්‍රභේදයකි T).

නිදසුනක් ලෙස, මෙය සිදුවන්නේ වර්ගයේ ආදාන පරාමිතියක් සහිත ශ්‍රිතයක් T(එනම් ආයාචනා කරන ලද) වර්ගයේ තර්ක අගය සමඟිනි S. නැතහොත්, වර්ගයේ හඳුනාගැනීමක් සඳහා, වර්ගයක Tඅගයක් පවරනු ලැබේ S.

val id : T = new S() // id thinks it's a T, but is a S

LSP සඳහා වර්ග T(උදා Rectangle) ක්‍රම සඳහා අපේක්ෂාවන් (එනම් වෙනස්වීම්) අවශ්‍ය වේ, ඒ වෙනුවට S(උදා Square) වර්ගයේ ක්‍රම කැඳවූ විට උල්ලං not නය නොවේ .

val rect : Rectangle = new Square(5) // thinks it's a Rectangle, but is a Square
val rect2 : Rectangle = rect.setWidth(10) // height is 10, LSP violation

වෙනස් කළ නොහැකි ක්ෂේත්‍ර සහිත වර්ගයක පවා තවමත් වෙනස්වීම් ඇත, උදා: වෙනස් කළ නොහැකි සෘජුකෝණාස්රාකාර සැකසුම්කරුවන් විසින් මානයන් ස්වාධීනව වෙනස් කරනු ඇතැයි අපේක්ෂා කරයි, නමුත් වෙනස් කළ නොහැකි චතුරස්ර සැකසුම්කරුවන් මෙම අපේක්ෂාව උල්ලං late නය කරයි.

class Rectangle( val width : Int, val height : Int )
{
   def setWidth( w : Int ) = new Rectangle(w, height)
   def setHeight( h : Int ) = new Rectangle(width, h)
}

class Square( val side : Int ) extends Rectangle(side, side)
{
   override def setWidth( s : Int ) = new Square(s)
   override def setHeight( s : Int ) = new Square(s)
}

එල්එස්පීයට අවශ්‍ය වන්නේ උප Sප්‍රභේදයේ එක් එක් ක්‍රමයට ප්‍රතිවිරෝධී ආදාන පරාමිතීන් සහ සහසංයුජ ප්‍රතිදානය තිබිය යුතුය.

පරස්පර විරෝධී යන්නෙන් අදහස් වන්නේ විචල්‍යතාවය උරුමයේ දිශාවට පටහැනි බවයි, එනම් Siඋප ප්‍රභේදයේ එක් එක් ක්‍රමයේ එක් එක් ආදාන පරාමිතියේ වර්ගය S, සුපර් ටයිප් Tiහි අනුරූප ක්‍රමයේ අනුරූප ආදාන පරාමිතියේ වර්ගයට සමාන හෝ සුපිරි ආකාරයක් විය යුතුය. T.

කෝවරියන්ස් යනු විචල්‍යතාවය උරුමයේ එකම දිශාවට ය, එනම් Soඋප ප්‍රභේදයේ එක් එක් ක්‍රමයේ ප්‍රතිදානයේ වර්ගය S, සුපර් ටයිප් Toහි අනුරූප ක්‍රමයේ අනුරූප ප්‍රතිදානයේ වර්ගයට සමාන හෝ උප වර්ගයක් විය යුතුය T.

මෙයට හේතුව ඇමතුම්කරුට එය වර්ගයක් ඇතැයි Tසිතන්නේ නම්, එය ක්‍රමවේදයක් යැයි සිතන්නේ නම්, එය වර්ගයේ Tතර්ක (ය) සපයන Tiඅතර ප්‍රතිදානය වර්ගයට පවරයි To. එය සැබවින්ම අනුරූප ක්‍රමයට කතා කරන විට S, එක් එක් Tiආදාන පරාමිතිය ආදාන පරාමිතියකට පවරා ඇති Siඅතර Soප්‍රතිදානය වර්ගයට පවරනු ලැබේ To. මේ අනුව නම් Siනොවේ contravariant wrt විය Ti, පසුව subtype Xiකලහ ක subtype වන්නේ නැහැ Siපවරා -could වේවා Ti.

මීට අමතරව, වර්ග බහුඅවයවික පරාමිතීන් (එනම් ජනක විද්‍යාව) පිළිබඳ අර්ථ දැක්වීම්-අඩවි විචල්‍යතා විවරණ ඇති භාෂා සඳහා (උදා: ස්කලා හෝ ලංකාව), එක් එක් වර්ගයේ පරාමිතීන් සඳහා විචල්‍ය විවරණයේ සම හෝ ප්‍රතිවිරුද්ධ දිශාව ප්‍රතිවිරුද්ධ හෝ එකම දිශාවකින් Tවිය යුතුය. පිළිවෙලින් වර්ගය පරාමිතිය ඇති සෑම ආදාන පරාමිතියකට හෝ ප්‍රතිදානයකට (සෑම ක්‍රමයකම ).T

මීට අමතරව, ශ්‍රිත වර්ගයක් ඇති එක් එක් ආදාන පරාමිතිය හෝ ප්‍රතිදානය සඳහා, අවශ්‍ය විචල්‍ය දිශාව ආපසු හරවනු ලැබේ. මෙම නියමය පුනරාවර්තනය වේ.


ආක්‍රමණ ගණනය කළ හැකි ස්ථානවල උප වර්ග කිරීම සුදුසුය .

ආක්‍රමණ ආදර්ශනය කරන්නේ කෙසේද යන්න පිළිබඳව බොහෝ පර්යේෂණ සිදු වෙමින් පවතින අතර එමඟින් ඒවා සම්පාදකයා විසින් බලාත්මක කරනු ලැබේ.

ටයිප්ස්ටේට් (3 වන පිටුව බලන්න) යතුරු ලියනය කිරීම සඳහා විකලාංග රාජ්‍ය ආක්‍රමණ ප්‍රකාශයට පත් කරයි. විකල්පයක් ලෙස, ප්‍රකාශයන් වර්ග බවට පරිවර්තනය කිරීමෙන් ආක්‍රමණ ක්‍රියාත්මක කළ හැකිය . උදාහරණයක් ලෙස, ගොනුවක් වැසීමට පෙර එය විවෘතව ඇති බව තහවුරු කර ගැනීම සඳහා, File.open () හට OpenFile වර්ගයක් ආපසු ලබා දිය හැකිය, එය ගොනුවේ නොමැති සමීප () ක්‍රමයක් අඩංගු වේ. සංයුක්ත වේලාවේදී ආක්‍රමණ ක්‍රියාත්මක කිරීමට ටයිප් කිරීම සඳහා ටික්-ටැක්-ටෝ ඒපීඅයි තවත් උදාහරණයක් විය හැකිය. වර්ගය පද්ධතිය ටියුරින්-සම්පුර්ණ විය හැකිය, උදා: පරිමාණය . යැපෙන ලෙස ටයිප් කළ භාෂා සහ ප්‍රමේය ප්‍රොවර්ස් ඉහළ පෙළේ ටයිප් කිරීමේ ආකෘති විධිමත් කරයි.

විස්තාරණයට වඩා අර්ථ නිරූපණයන්හි අවශ්‍යතාවය නිසා, ආකෘති ආක්‍රමණ සඳහා යතුරු ලියනය කිරීම, එනම් ඒකාබද්ධ ඉහළ පෙළේ අර්ථ දැක්වීමේ අර්ථ නිරූපණය ටයිප්ස්ටේටයට වඩා උසස් යැයි මම අපේක්ෂා කරමි. 'ව්‍යාප්තිය' යනු සම්බන්ධීකරනය නොකළ, මොඩියුලර් සංවර්ධනයේ අසීමිත, අවසර ලත් සංයුතියයි. විස්තාරණ සංයුතිය සඳහා එකිනෙකා සමඟ ඒකාබද්ධ කළ නොහැකි, හවුල් අර්ථකථන ප්‍රකාශ කිරීම සඳහා අන්‍යෝන්‍ය වශයෙන් රඳා පවතින ආකෘති දෙකක් (උදා: වර්ග සහ ටයිප්ස්ටේට්) තිබීම, ඒකීයභාවයේ ප්‍රතිවිරෝධය ලෙස මට පෙනේ. . නිදසුනක් ලෙස, ප්‍රකාශන ගැටළුව- සමාන දිගුව උප වර්ගය, ක්‍රියාකාරී අධි බර පැටවීම සහ පරාමිතික ටයිප් කිරීමේ වසම් තුළ ඒකාබද්ධ විය.

මගේ න්‍යායාත්මක ස්ථාවරය නම් දැනුම පැවතීම සඳහා (“මධ්‍යගත කිරීම අන්ධ හා නුසුදුසු” යන කොටස බලන්න), ටියුරින්-සම්පූර්ණ පරිගණක භාෂාවක් තුළ ඇති විය හැකි සියලු වෙනස්වීම් 100% ක් ආවරණය කළ හැකි පොදු ආකෘතියක් කිසි විටෙකත් නොතිබෙනු ඇත . දැනුම පැවතීමට නම්, අනපේක්ෂිත හැකියාවන් බොහෝමයක් පවතී, එනම් ආබාධය සහ එන්ට්‍රොපිය සෑම විටම වැඩි විය යුතුය. මෙය එන්ට්‍රොපික් බලයයි. විභව දිගුවක ඇති විය හැකි සියලුම ගණනය කිරීම් සනාථ කිරීම සඳහා, හැකි සෑම දිගුවක්ම ප්‍රාථමික ගණනය කිරීමකි.

හැල්ටිං ප්‍රමේය පවතින්නේ මේ නිසාය, එනම් ටියුරින්-සම්පූර්ණ ක්‍රමලේඛන භාෂාවක හැකි සෑම වැඩසටහනක්ම අවසන් වේද යන්න තීරණය කළ නොහැක. සමහර විශේෂිත වැඩසටහන් අවසන් වන බව සනාථ කළ හැකිය (සියලු හැකියාවන් නිර්වචනය කර ගණනය කර ඇති එකක්). නමුත් එම වැඩසටහන දීර් extension කිරීමේ හැකියාවන් සම්පූර්ණ නොවේ නම් (උදා: යැපුම්-ටයිප් කිරීම හරහා) එම වැඩසටහනේ දීර් extension කිරීමේ හැකියාව අවසන් වන බව ඔප්පු කළ නොහැක. ටියුරින්-සම්පූර්ණත්වය සඳහා වන මූලික අවශ්‍යතාව අසීමිත පුනරාවර්තනයක් බැවින් , ගොඩෙල්ගේ අසම්පූර්ණ ප්‍රමේයයන් සහ රසල්ගේ විරුද්ධාභාසය දීර්. කිරීම සඳහා අදාළ වන්නේ කෙසේද යන්න තේරුම් ගැනීම බුද්ධිමත් ය.

මෙම ප්‍රමේයයන්ගේ අර්ථ නිරූපණය එන්ට්‍රොපික් බලය පිළිබඳ සාමාන්‍යකරණය වූ සංකල්පීය අවබෝධයකට ඒවා ඇතුළත් කරයි:

  • ගොඩෙල්ගේ අසම්පූර්ණ ප්‍රමේයයන් : සියලු ගණිතමය සත්‍යයන් සනාථ කළ හැකි ඕනෑම විධිමත් න්‍යායක් නොගැලපේ.
  • රසල්ගේ විරුද්ධාභාසය : කට්ටලයක් අඩංගු විය හැකි කට්ටලයක් සඳහා වන සෑම සාමාජිකත්ව රීතියක්ම , එක් එක් සාමාජිකයාගේ නිශ්චිත වර්ගය ගණනය කිරීම හෝ එහි අඩංගු වේ. මේ අනුව කට්ටල දිගු කළ නොහැක, නැතහොත් ඒවා අසීමිත පුනරාවර්තනයකි. නිදසුනක් ලෙස, තේ පෝච්චියක් නොවන සෑම දෙයකම කට්ටලයම ඇතුළත් වේ, එය තමාටම ඇතුලත් වේ, එයට ඇතුළත් වේ, ආදිය…. මේ අනුව රීතියක් නොගැලපේ (එය කට්ටලයක් අඩංගු විය හැකි අතර) නිශ්චිත වර්ග ගණනය නොකරන්නේ නම් (එනම් සියලු නිශ්චිත නොවන වර්ග වලට ඉඩ දෙයි) සහ අසීමිත දිගුවකට ඉඩ නොදේ. මෙය තමන් විසින්ම සාමාජිකයන් නොවන කට්ටල සමූහයකි. හැකි සෑම දිගුවකටම අනුකූලව හා සම්පූර්ණයෙන් ගණනය කිරීමට මෙම නොහැකියාව, ගොඩෙල්ගේ අසම්පූර්ණ ප්‍රමේයයන් වේ.
  • ලිස්කොව් ආදේශන මූලධර්මය : සාමාන්‍යයෙන් එය කිසියම් කට්ටලයක් තවත් උප කුලකයක්ද යන්න නිශ්චිතවම කිව නොහැකි ගැටළුවකි, එනම් උරුමය සාමාන්‍යයෙන් තීරණය කළ නොහැකි ය.
  • ලින්ස්කි යොමු කිරීම : යමක් ගණනය කිරීම යනු කුමක්ද යන්න විස්තර කළ විට හෝ වටහා ගත් විට, එනම් සංජානනය (යථාර්ථය) යන්නට නිරපේක්ෂ යොමු ලක්ෂ්‍යයක් නොමැත.
  • කෝස්ගේ ප්‍රමේයය : බාහිර යොමු ලක්ෂ්‍යයක් නොමැත, එබැවින් අසීමිත බාහිර හැකියාවන්ට ඇති බාධකයක් අසාර්ථක වනු ඇත.
  • තාප ගති විද්‍යාවේ දෙවන නියමය : මුළු විශ්වයම (සංවෘත පද්ධතියක්, එනම් සියල්ල) උපරිම ආබාධයට නැඹුරු වේ, එනම් උපරිම ස්වාධීන හැකියාවන්.

17
She ෂෙලිබි: ඔබ බොහෝ දේ මිශ්‍ර කර ඇත. ඔබ පවසන පරිදි දේවල් අවුල් සහගත නොවේ. ඔබේ න්‍යායාත්මක ප්‍රකාශයන්ගෙන් බොහොමයක් 'දැනුම පැවතීමට නම්, අනපේක්ෂිත හැකියාවන් බොහෝමයක් පවතී, .........' සහ 'වැනි ඕනෑම පදනමක් මත පදනම් වේ. උරුමය සාමාන්‍යයෙන් තීරණය කළ නොහැකි ය. මෙම සෑම කරුණක් සඳහාම ඔබට වෙනම බ්ලොග් අඩවියක් ආරම්භ කළ හැකිය. කෙසේ වෙතත්, ඔබේ ප්‍රකාශ සහ උපකල්පන අතිශයින්ම සැක සහිත ය. යමෙකු නොදන්නා දේවල් භාවිතා නොකළ යුතුය!
aknon

1
මේ කාරණා වඩාත් ගැඹුරින් පැහැදිලි කරන බ්ලොග් අඩවියක් මා සතුව ඇත . මගේ TOE මාදිලියේ අසීමිත අභ්‍යවකාශ කාලය අසීමිත සංඛ්‍යාත වේ. පුනරාවර්තන ප්‍රේරක ශ්‍රිතයක් අසීමිත අවසානයක් සහිත දන්නා ආරම්භක අගයක් ඇති බව හෝ ව්‍යාකූල ශ්‍රිතයක් නොදන්නා අවසාන අගයක් සහ දන්නා ආරම්භක බැඳීමක් ඇති බව මට ව්‍යාකූල නොවේ. සාපේක්ෂතාවාදය යනු පුනරාවර්තනය හඳුන්වා දුන් පසු ගැටළුවයි. ටියුරින් සම්පුර්ණ කිරීම අසීමිත පුනරාවර්තනයකට සමාන වන්නේ මේ නිසා ය .
ෂෙල්බි මුවර් III

4
SheShelbyMooreIII ඔබ බොහෝ දිශාවලට ගමන් කරයි. මෙය පිළිතුරක් නොවේ.
සොල්ඩල්මා

1
Old සොල්ඩල්මා එය පිළිතුරකි. ඔබට එය පිළිතුරු කොටසේ නොපෙනේද? ඔබගේ අදහස් දැක්වීමක් වන්නේ එය අදහස් දැක්වීමේ කොටසෙහි ඇති බැවිනි.
ෂෙල්බි මුවර් III

1
ඔබ පරිමාණ ලෝකය සමඟ මිශ්‍ර වූවාක් මෙන්!
එහ්සාන් එම්. කර්මනී

28

සෑම පිළිතුරකම සෘජුකෝණාස්රා සහ චතුරස්රයන් සහ එල්එස්පී උල්ලං how නය කරන්නේ කෙසේදැයි මම දකිමි.

එල්එස්පී සැබෑ ලෝක උදාහරණයකට අනුකූල වන්නේ කෙසේදැයි පෙන්වීමට මම කැමතියි:

<?php

interface Database 
{
    public function selectQuery(string $sql): array;
}

class SQLiteDatabase implements Database
{
    public function selectQuery(string $sql): array
    {
        // sqlite specific code

        return $result;
    }
}

class MySQLDatabase implements Database
{
    public function selectQuery(string $sql): array
    {
        // mysql specific code

        return $result; 
    }
}

මෙම සැලසුම එල්එස්පීයට අනුකූල වන්නේ අප භාවිතා කිරීමට තෝරා ගැනීම ක්‍රියාත්මක කිරීම නොසලකා හැසිරීම නොවෙනස්ව පවතින බැවිනි.

ඔව්, ඔබට මෙම වින්‍යාසය තුළ එල්එස්පී උල්ලං can නය කළ හැකිය.

<?php

interface Database 
{
    public function selectQuery(string $sql): array;
}

class SQLiteDatabase implements Database
{
    public function selectQuery(string $sql): array
    {
        // sqlite specific code

        return $result;
    }
}

class MySQLDatabase implements Database
{
    public function selectQuery(string $sql): array
    {
        // mysql specific code

        return ['result' => $result]; // This violates LSP !
    }
}

දැන් උප ප්‍රභේද එකම ආකාරයකින් භාවිතා කළ නොහැක, මන්ද ඒවා තවදුරටත් එකම ප්‍රති result ලය ලබා නොදේ.


8
සියලුම ඩීබී එන්ජින් Database::selectQueryමඟින් සහය දක්වන SQL හි උප කුලකයට සහය දැක්වීමේ අර්ථ නිරූපණය අප විසින් සීමා කරන තාක් කල් උදාහරණය එල්එස්පී උල්ලං does නය නොකරයි . එය කිසිසේත්ම ප්‍රායෝගික නොවේ ... එයින් කියැවෙන්නේ මෙහි භාවිතා කර ඇති අනෙක් ඒවාට වඩා උදාහරණය තවමත් ග්‍රහණය කර ගැනීම පහසු බවය.
පලෙක්

6
මෙම පිළිතුර සෙසු ඒවායින් ග්‍රහණය කර ගැනීමට පහසුම බව මට පෙනී ගියේය.
මැල්කම් සැල්වදෝර්

දත්ත සමුදායන් මත LSP යෙදීම ප්‍රායෝගිකද? බොහෝමයක්, එසේ නොවුවහොත්, ඩීබී මෙහෙයුම් සියල්ලම එතීමට අවශ්‍ය වනු ඇති අතර වැරදි වලට ගොදුරු විය හැකි බව මට පෙනේ. හොඳ පැත්තක් වුවද ඒපීඅයි එය එදිරිව පවතින්නේ SQL එදිරිව NoSQL වුවද.
ෂෝන් ඩබ්ලිව්

26

ඔබ ලිස්කොව් උල්ලං are නය කරනවාද නැද්ද යන්න තීරණය කිරීම සඳහා චෙක් ලැයිස්තුවක් තිබේ.

  • ඔබ පහත අයිතම වලින් එකක් උල්ලං If නය කරන්නේ නම් -> ඔබ ලිස්කොව් උල්ලං late නය කරයි.
  • ඔබ කිසිවක් උල්ලං do නය නොකරන්නේ නම් -> කිසිවක් නිගමනය කළ නොහැක.

පිරික්සුම් ලැයිස්තුව:

  • ව්‍යුත්පන්න පංතියේ නව ව්‍යතිරේකයන් නොතැබිය යුතුය : ඔබේ මූලික පංතිය ArgumentNullException විසි කළහොත් ඔබේ උප පංතිවලට අවසර දී ඇත්තේ ArgumentNullException වර්ගයේ ව්‍යතිරේකයන් හෝ ArgumentNullException වෙතින් ලබාගත් ව්‍යතිරේකයන් පමණි. IndexOutOfRangeException විසි කිරීම ලිස්කොව් උල්ලං violation නය කිරීමකි.
  • පූර්ව කොන්දේසි ශක්තිමත් කළ නොහැක : ඔබේ මූලික පන්තිය සාමාජිකයෙකු සමඟ ක්‍රියා කරයි යැයි උපකල්පනය කරන්න. දැන් ඔබේ උප වර්ගය සඳහා එම int ධනාත්මක විය යුතුය. මෙය පූර්ව කොන්දේසි ශක්තිමත් කර ඇති අතර දැන් negative ණාත්මක තීන්ත සමඟ හොඳින් ක්‍රියා කළ ඕනෑම කේතයක් කැඩී ඇත.
  • පශ්චාත්-කොන්දේසි දුර්වල කළ නොහැක : ඔබේ මූලික පන්තියට අවශ්‍ය යැයි සිතන්න දත්ත ගබඩාවට ඇති සියලුම සම්බන්ධතා නැවත පැමිණීමට පෙර වසා දැමිය යුතුය. ඔබේ උප පංතියේ දී ඔබ එම ක්‍රමය ඉක්මවා ගොස් නැවත භාවිතා කිරීම සඳහා සම්බන්ධතාවය විවෘත කර ඇත. ඔබ එම ක්‍රමයේ පශ්චාත් කොන්දේසි දුර්වල කර ඇත.
  • අන්තරායන් ආරක්ෂා කළ යුතුය : ඉටු කිරීමට වඩාත්ම දුෂ්කර හා වේදනාකාරී බාධකය. අක්‍රමිකතා යම් කාලයක් මූලික පන්තියේ සැඟවී ඇති අතර ඒවා හෙළි කිරීමට ඇති එකම ක්‍රමය මූලික පන්තියේ කේතය කියවීමයි. මූලික වශයෙන් ඔබ ක්‍රමවේදයක් ඉක්මවා යන විට වෙනස් කළ හැකි කිසිවක් ඔබගේ අභිබවා ගිය ක්‍රමය ක්‍රියාත්මක කිරීමෙන් පසුව නොවෙනස්ව පැවතිය යුතුය. මට සිතිය හැකි හොඳම දෙය නම් මූලික පන්තියේ මෙම වෙනස් නොවන සීමාවන් බලාත්මක කිරීමයි, නමුත් එය පහසු නොවනු ඇත.
  • ඉතිහාසය අවහිර කිරීම : ක්‍රමවේදයක් ඉක්මවා යන විට මූලික පන්තියේ වෙනස් කළ නොහැකි දේපලක් වෙනස් කිරීමට ඔබට අවසර නැත. මෙම කේතය දෙස බලන්න, නම වෙනස් කළ නොහැකි (පුද්ගලික කට්ටලයක්) ලෙස අර්ථ දක්වා ඇති නමුත් උප ටයිප් නව ක්‍රමයක් හඳුන්වා දෙන අතර එය වෙනස් කිරීමට ඉඩ සලසයි (පරාවර්තනය හරහා):

    public class SuperType
    {
        public string Name { get; private set; }
        public SuperType(string name, int age)
        {
            Name = name;
            Age = age;
        }
    }
    public class SubType : SuperType
    {
        public void ChangeName(string newName)
        {
            var propertyType = base.GetType().GetProperty("Name").SetValue(this, newName);
        }
    }
    

: 2 අන් අය භාණ්ඩ ඇත ක්රමය තර්ක Contravariance හා නැවත වර්ග Covariance . නමුත් එය C # හි කළ නොහැකි ය (මම C # සංවර්ධකයෙක්) එබැවින් මම ඔවුන් ගැන තැකීමක් නොකරමි.

යොමුව:


මම සී # සංවර්ධකයෙක් වන අතර .නෙට් 4.0 රාමුව සමඟින් ඔබේ අවසාන ප්‍රකාශය විෂුවල් ස්ටුඩියෝ 2010 වන විට සත්‍ය නොවන බව මම කියමි. ආපසු පැමිණීමේ වර්ගවල සහසම්බන්ධය අතුරුමුහුණත මගින් අර්ථ දක්වා ඇති ප්‍රමාණයට වඩා ව්‍යුත්පන්න ප්‍රතිලාභ වර්ගයක් සඳහා ඉඩ ලබා දේ. උදාහරණය: උදාහරණය: IEnumerable <T> (T යනු සහසංයුජයි) IEnumerator <T> (T යනු සහසංයුජයි) IQueryable <T> (T යනු සහසංයුජයි) IEqualityComparer <T> (T contravariant) IComparable <T> (T contravariant) msdn.microsoft.com/en-us/library/dd233059(v=vs.100).aspx
LCarter

1
විශිෂ්ට සහ නාභිගත කළ පිළිතුර (මුල් ප්‍රශ්න නීතිවලට වඩා උදාහරණ ගැන වුවද).
මයික්

22

එල්එස්පී යනු වගන්තිවල කොන්ත්රාත්තුව පිළිබඳ රීතියකි: මූලික පංතියක් කොන්ත්රාත්තුවක් තෘප්තිමත් කරන්නේ නම්, එල්එස්පී ව්යුත්පන්න පංති විසින් ද එම කොන්ත්රාත්තුව සපුරාලිය යුතුය.

ව්‍යාජ පයිතන්හි

class Base:
   def Foo(self, arg): 
       # *... do stuff*

class Derived(Base):
   def Foo(self, arg):
       # *... do stuff*

ව්‍යුත්පන්න වස්තුවක් මත ඔබ Foo අමතන සෑම අවස්ථාවකම එය LSP තෘප්තිමත් කරයි, එය Arg සමාන වන තාක් දුරට මූලික වස්තුවක් මත Foo ඇමතීමට සමාන ප්‍රති results ල ලබා දෙයි.


9
නමුත් ... ඔබ සැමවිටම එකම හැසිරීමක් ලබා ගන්නේ නම්, ව්‍යුත්පන්න පංතිය තිබීමේ තේරුම කුමක්ද?
ලියොනිඩ්

2
ඔබට කරුණක් මග හැරුණි: එය නිරීක්ෂණය කළ හැසිරීමම වේ. උදාහරණයක් ලෙස, ඔබට O (n) කාර්ය සාධනය සමඟ යමක් ක්‍රියාකාරී ලෙස සමාන, නමුත් O (lg n) කාර්ය සාධනය සමඟ ආදේශ කළ හැකිය. නැතහොත් ඔබට MySQL සමඟ ක්‍රියාත්මක කරන ලද දත්ත වලට ප්‍රවේශ වන යමක් ප්‍රතිස්ථාපනය කර එය මතකයේ ඇති දත්ත ගබඩාවක් සමඟ ප්‍රතිස්ථාපනය කළ හැකිය.
චාලි මාටින්

Har චාර්ලි මාටින්, ක්‍රියාත්මක කිරීමට වඩා අතුරු මුහුණතකට කේත කිරීම - මම එය හාරමි. මෙය OOP ට පමණක් ආවේණික නොවේ; ක්ලෝජුර් වැනි ක්‍රියාකාරී භාෂාවන් ද එය ප්‍රවර්ධනය කරයි. ජාවා හෝ සී # අනුව වුවද, වියුක්ත පංතියක් සහ පන්ති ධූරාවලියක් භාවිතා කරනවාට වඩා අතුරු මුහුණතක් භාවිතා කිරීම ඔබ සපයන උදාහරණ සඳහා ස්වාභාවික වනු ඇතැයි මම සිතමි. පයිතන් තදින් ටයිප් කර නැති අතර ඇත්ත වශයෙන්ම අතුරු මුහුණත් නොමැත, අවම වශයෙන් පැහැදිලිවම නැත. මගේ දුෂ්කරතාවය නම්, මම SOLID වලට අනුගත නොවී වසර ගණනාවක් OOP කරමින් සිටීමයි. දැන් මට එය හමු වූ විට, එය සීමිත හා ස්වයං-පරස්පර විරෝධී බවක් පෙනේ.
හාමිෂ් ග්‍රුබිජන්

හොඳයි, ඔබ ආපසු ගොස් බාබරාගේ මුල් කඩදාසි බලන්න. report-archive.adm.cs.cmu.edu/anon/1999/CMU-CS-99-156.ps එය ඇත්ත වශයෙන්ම අතුරුමුහුණත් අනුව ප්‍රකාශ කර නැති අතර එය තාර්කික relation ාතියකි. යම් ආකාරයක උරුමයක් ඇති ක්‍රමලේඛන භාෂාව.
චාලි මාටින්

1
@ හමීෂ් ග්‍රුබිජන් පයිතන් තදින් ටයිප් කර නැති බව ඔබට කීවේ කවුදැයි මම නොදනිමි, නමුත් ඔවුන් ඔබට බොරු කීහ (ඔබ මාව විශ්වාස නොකරන්නේ නම්, පයිතන් පරිවර්තකයෙකුට වෙඩි තබා උත්සාහ කරන්න 2 + "2"). සමහර විට ඔබ "තදින් ටයිප් කළ" "සංඛ්‍යානමය වශයෙන් ටයිප් කළ" ලෙස පටලවා ගන්නවාද?
asmeurer

22

දීර් story කතන්දර කෙටියි, සෘජුකෝණාස්රාකාර හතරැස් සහ චතුරස්ර චතුරස්රයන් තබමු, මව් පංතියක් දීර් ing කිරීමේදී ප්රායෝගික උදාහරණය, ​​ඔබට නිශ්චිත මාපිය API පෙරදසුන් කිරීම හෝ එය දිගු කිරීම කළ යුතුය.

අපි ඔබට මූලික අයිතම ගබඩාවක් ඇති බව කියමු.

class ItemsRepository
{
    /**
    * @return int Returns number of deleted rows
    */
    public function delete()
    {
        // perform a delete query
        $numberOfDeletedRows = 10;

        return $numberOfDeletedRows;
    }
}

එය දීර් ing කරන උප පංතියක්:

class BadlyExtendedItemsRepository extends ItemsRepository
{
    /**
     * @return void Was suppose to return an INT like parent, but did not, breaks LSP
     */
    public function delete()
    {
        // perform a delete query
        $numberOfDeletedRows = 10;

        // we broke the behaviour of the parent class
        return;
    }
}

එවිට ඔබට සේවාදායකයෙකුට මූලික අයිතම රිපෝසිටරි ඒපීඅයි සමඟ වැඩ කර එය මත විශ්වාසය තැබිය හැකිය.

/**
 * Class ItemsService is a client for public ItemsRepository "API" (the public delete method).
 *
 * Technically, I am able to pass into a constructor a sub-class of the ItemsRepository
 * but if the sub-class won't abide the base class API, the client will get broken.
 */
class ItemsService
{
    /**
     * @var ItemsRepository
     */
    private $itemsRepository;

    /**
     * @param ItemsRepository $itemsRepository
     */
    public function __construct(ItemsRepository $itemsRepository)
    {
        $this->itemsRepository = $itemsRepository;
    }

    /**
     * !!! Notice how this is suppose to return an int. My clients expect it based on the
     * ItemsRepository API in the constructor !!!
     *
     * @return int
     */
    public function delete()
    {
        return $this->itemsRepository->delete();
    }
} 

මෙම LSP විට කැඩී ඇත ආදේශ මව් සමඟ පන්ති උප පන්තිය වැලහින්නිය API කොන්ත්රාත්තුව .

class ItemsController
{
    /**
     * Valid delete action when using the base class.
     */
    public function validDeleteAction()
    {
        $itemsService = new ItemsService(new ItemsRepository());
        $numberOfDeletedItems = $itemsService->delete();

        // $numberOfDeletedItems is an INT :)
    }

    /**
     * Invalid delete action when using a subclass.
     */
    public function brokenDeleteAction()
    {
        $itemsService = new ItemsService(new BadlyExtendedItemsRepository());
        $numberOfDeletedItems = $itemsService->delete();

        // $numberOfDeletedItems is a NULL :(
    }
}

නඩත්තු කළ හැකි මෘදුකාංග ලිවීම පිළිබඳ මගේ පා ​​course මාලාවෙන් ඔබට වැඩිදුර ඉගෙන ගත හැකිය: https://www.udemy.com/enterprise-php/


21

එල්එස්පී තාක්‍ෂණිකව ඇති දේ සෑම කෙනෙකුම ආවරණය කර ඇති බව මම අනුමාන කරමි: ඔබට මූලික වශයෙන් අවශ්‍ය වන්නේ උප වර්ග විස්තර වලින් වියුක්ත වී සුපිරි ටයිප් ආරක්ෂිතව භාවිතා කිරීමට ය.

එබැවින් ලිස්කොව්ට යටින් පවතින නීති 3 ක් ඇත:

  1. අත්සන රීතිය: උප ප්‍රභේදයේ සුපිරි මාදිලියේ සෑම ක්‍රියාවක්ම සින්ටැක්ටිකල් ලෙස වලංගු ලෙස ක්‍රියාත්මක කළ යුතුය. සම්පාදකයෙකුට ඔබ වෙනුවෙන් පරීක්ෂා කිරීමට හැකි වනු ඇත. අඩු ව්‍යතිරේකයන් විසි කිරීම සහ අවම වශයෙන් සුපිරි ටයිප් ක්‍රමවලට ප්‍රවේශ විය හැකි වීම පිළිබඳ කුඩා රීතියක් තිබේ.

  2. ක්‍රම රීතිය: එම මෙහෙයුම් ක්‍රියාත්මක කිරීම අර්ථාන්විත ය.

    • දුර්වල පූර්ව කොන්දේසි: උප ප්‍රභේද ශ්‍රිතයන් අවම වශයෙන් සුපර් ටයිප් ආදානය ලෙස ගත් දේ වත් ගත යුතුය.
    • වඩා ශක්තිමත් පසු කොන්දේසි: ඔවුන් විසින් නිපදවන සුපිරි ටයිප් ක්‍රමයේ ප්‍රතිදානයේ උප කුලකයක් නිෂ්පාදනය කළ යුතුය.
  3. ගුණාංග රීතිය: මෙය තනි ක්‍රියාකාරී ඇමතුම් ඉක්මවා යයි.

    • වෙනස්වීම්: සැමවිටම සත්‍ය වන දේ සත්‍ය ලෙස පැවතිය යුතුය. උදා. කට්ටලයක ප්‍රමාණය කිසි විටෙකත් .ණාත්මක නොවේ.
    • පරිණාමීය ගුණාංග: සාමාන්‍යයෙන් වෙනස් කළ නොහැකි දෙයක් හෝ වස්තුව පැවතිය හැකි ආකාරයේ තත්වයන් සමඟ කළ හැකි දෙයක්. නැතහොත් සමහර විට වස්තුව පමණක් වර්ධනය වන අතර කිසි විටෙකත් හැකිලෙන්නේ නැත.

මෙම සියලු ගුණාංග සංරක්ෂණය කළ යුතු අතර අතිරේක උප ප්‍රභේදයේ ක්‍රියාකාරිත්වය සුපිරි ටයිප් ගුණාංග උල්ලං not නය නොකළ යුතුය.

මෙම කරුණු තුන ගැන සැලකිලිමත් වන්නේ නම්, ඔබ යටින් පවතින දේවලින් වියුක්ත වී ඇති අතර ඔබ ලිහිල්ව සම්බන්ධිත කේතයක් ලියයි.

මූලාශ්‍රය: ජාවා හි වැඩසටහන් සංවර්ධනය - බාබරා ලිස්කොව්


20

පාදක පංති වෙත යොමු කිරීම් හෝ යොමු කිරීම් භාවිතා කරන කාර්යයන් නොදැන ව්‍යුත්පන්න පංතිවල වස්තු භාවිතා කළ යුතුය.

එල්එස්පී ගැන මා මුලින් කියවූ විට, මෙය ඉතා දැඩි අර්ථයකින් අදහස් කළ බව උපකල්පනය කළෙමි. එයින් අදහස් වන්නේ එල්එස්පී සහතික කරනු ලබන්නේ හෝ භාෂාව විසින්ම නොවන බවයි. උදාහරණයක් ලෙස, මෙම දැඩි අර්ථයෙන් ගත් කල, සම්පාදකයාට අනුව, ත්‍රි ඩී බෝඩ් නිසැකවම මණ්ඩලයට ආදේශ කළ හැකිය.

එල්එස්පී සාමාන්‍යයෙන් ඊට වඩා පුළුල් ලෙස අර්ථකථනය කර ඇති බව මට පෙනී ගියද, සංකල්පය පිළිබඳ වැඩිදුර කියවීමෙන් පසුව මට පෙනී ගියේය.

කෙටියෙන් කිවහොත්, ග්‍රාහක කේතයට “දැනගැනීම” යන්නෙන් අදහස් කරන්නේ දර්ශකයේ පිටුපස ඇති වස්තුව දර්ශක වර්ගයට වඩා ව්‍යුත්පන්න වර්ගයක් බව ටයිප්-ආරක්ෂාවට පමණක් සීමා නොවේ. වස්තූන්ගේ සැබෑ හැසිරීම පරීක්ෂා කිරීම තුළින් එල්එස්පී පිළිපැදීම ද පරීක්ෂා කළ හැකිය. එනම්, ක්‍රම ඇමතුම්වල ප්‍රති results ල මත වස්තුවක තත්වය සහ ක්‍රම තර්ක වල බලපෑම හෝ වස්තුවෙන් විසි කරන ව්‍යතිරේක වර්ග පරීක්ෂා කිරීම.

නැවත උදාහරණයට යාම, න්‍යායිකව , ත්‍රි ඩී බෝඩ් හි හොඳින් ක්‍රියා කිරීමට මණ්ඩල ක්‍රමවේදයන් සකස් කළ හැකිය. කෙසේ වෙතත්, ප්‍රායෝගිකව, ThreeDBoard එකතු කිරීමට අදහස් කරන ක්‍රියාකාරීත්වයට බාධා නොකර, සේවාදායකයා නිසි ලෙස හැසිරවිය නොහැකි හැසිරීම් වල වෙනස්කම් වැළැක්වීම ඉතා අපහසු වනු ඇත.

මෙම දැනුම අතේ ඇති හෙයින්, උරුමය වෙනුවට පවත්නා ක්‍රියාකාරිත්වය දීර් for කිරීම සඳහා සංයුතිය වඩාත් සුදුසු යාන්ත්‍රණය වන්නේ කවදාද යන්න තීරණය කිරීම සඳහා එල්එස්පී පිළිපැදීම ඇගයීම හොඳ මෙවලමක් විය හැකිය.


19

එල්එස්පී භාවිතය පිළිබඳ වැදගත් උදාහරණයක් වන්නේ මෘදුකාංග පරීක්ෂාවයි .

මට B පන්තියේ LSP අනුකූල උප පංතියක් වන A පන්තියක් තිබේ නම්, මට A පරීක්ෂා කිරීම සඳහා B හි පරීක්ෂණ කට්ටලය නැවත භාවිතා කළ හැකිය.

උප පංතිය A සම්පූර්ණයෙන් පරීක්ෂා කිරීම සඳහා, මට තවත් පරීක්ෂණ අවස්ථා කිහිපයක් එකතු කිරීමට අවශ්‍ය වනු ඇත, නමුත් අවම වශයෙන් මට සුපිරි පන්තියේ B හි පරීක්ෂණ අවස්ථා සියල්ලම නැවත භාවිතා කළ හැකිය.

අවබෝධ කර ගත හැකි ක්‍රමයක් නම් මැක්ග්‍රෙගර් “පරීක්ෂණ සඳහා සමාන්තර ධූරාවලියක්” ලෙස හැඳින්වීමයි: මගේ ATestපන්තිය උරුම වනු ඇත BTest. පරීක්ෂණ අවස්ථාව B වර්ගයට වඩා A වර්ගයේ වස්තූන් සමඟ ක්‍රියා කරන බව සහතික කිරීම සඳහා යම් ආකාරයක එන්නත් කිරීමක් අවශ්‍ය වේ (සරල අච්චු ක්‍රම රටාවක් මඟින් කරනු ඇත).

සියළුම උප පංති ක්‍රියාත්මක කිරීම් සඳහා සුපිරි පරීක්ෂණ කට්ටලය නැවත භාවිතා කිරීම ඇත්ත වශයෙන්ම මෙම උප පංති ක්‍රියාත්මක කිරීම් එල්එස්පී අනුකූලදැයි පරීක්ෂා කිරීමට ක්‍රමයක් බව සලකන්න. මේ අනුව, ඕනෑම උප පංතියක සන්දර්භය තුළ යමෙකු සුපිරි පන්තියේ පරීක්ෂණ කට්ටලය ධාවනය කළ යුතු යැයි කෙනෙකුට තර්ක කළ හැකිය .

" අතුරු මුහුණතක් ක්‍රියාත්මක කිරීම පරීක්ෂා කිරීම සඳහා නැවත භාවිතා කළ හැකි පරීක්ෂණ මාලාවක් ක්‍රියාත්මක කළ හැකිද? "


18

ජාවා හි නිදර්ශනය කරමු:

class TrasportationDevice
{
   String name;
   String getName() { ... }
   void setName(String n) { ... }

   double speed;
   double getSpeed() { ... }
   void setSpeed(double d) { ... }

   Engine engine;
   Engine getEngine() { ... }
   void setEngine(Engine e) { ... }

   void startEngine() { ... }
}

class Car extends TransportationDevice
{
   @Override
   void startEngine() { ... }
}

මෙතන කිසිම ප්‍රශ්නයක් නැහැ නේද? මෝටර් රථයක් අනිවාර්යයෙන්ම ප්‍රවාහන උපකරණයක් වන අතර මෙහිදී අපට දැක ගත හැකි වන්නේ එය එහි සුපිරි පන්තියේ ආරම්භක එන්ජින් () ක්‍රමය ඉක්මවා යන බවයි.

අපි තවත් ප්‍රවාහන උපාංගයක් එකතු කරමු:

class Bicycle extends TransportationDevice
{
   @Override
   void startEngine() /*problem!*/
}

දැන් සියල්ල සැලසුම් කළ පරිදි සිදු නොවේ! ඔව්, බයිසිකලයක් යනු ප්‍රවාහන උපකරණයකි, කෙසේ වෙතත් එයට එන්ජිමක් නොමැති අතර ඒ නිසා ආරම්භක එන්ජින් () ක්‍රමය ක්‍රියාත්මක කළ නොහැක.

ලිස්කොව් ආදේශන මූලධර්මය උල්ලං violation නය කිරීමට හේතු වන ගැටළු මේවා වන අතර ඒවා බොහෝ විට හඳුනාගත හැක්කේ කිසිවක් නොකරන හෝ ක්‍රියාත්මක කළ නොහැකි ක්‍රමවේදයක් මගිනි.

මෙම ගැටළුවලට විසඳුම නිවැරදි උරුම ධූරාවලියක් වන අතර, අපගේ නඩුවේදී අපි එන්ජින් සමඟ සහ රහිතව ප්‍රවාහන උපකරණ වර්ග වෙන්කර හඳුනා ගැනීමෙන් ගැටළුව විසඳන්නෙමු. බයිසිකලයක් ප්‍රවාහන උපකරණයක් වුවද එයට එන්ජිමක් නොමැත. මෙම උදාහරණයේ දී ප්‍රවාහන උපාංගය පිළිබඳ අපගේ අර්ථ දැක්වීම වැරදිය. එයට එන්ජිමක් නොතිබිය යුතුය.

අපගේ ප්‍රවාහන සේවා පන්තිය පහත පරිදි ප්‍රතිනිර්මාණය කළ හැකිය:

class TrasportationDevice
{
   String name;
   String getName() { ... }
   void setName(String n) { ... }

   double speed;
   double getSpeed() { ... }
   void setSpeed(double d) { ... }
}

දැන් අපට මෝටර් නොවන උපාංග සඳහා ප්‍රවාහන සේවය දීර් extend කළ හැකිය.

class DevicesWithoutEngines extends TransportationDevice
{  
   void startMoving() { ... }
}

යතුරුපැදි උපාංග සඳහා ප්‍රවාහන සේවය දීර් extend කරන්න. එන්ජින් වස්තුව එකතු කිරීම සඳහා වඩාත් සුදුසු වේ.

class DevicesWithEngines extends TransportationDevice
{  
   Engine engine;
   Engine getEngine() { ... }
   void setEngine(Engine e) { ... }

   void startEngine() { ... }
}

මේ අනුව ලිස්කොව් ආදේශන මූලධර්මයට අනුකූලව අපගේ කාර් පන්තිය වඩාත් විශේෂිත වේ.

class Car extends DevicesWithEngines
{
   @Override
   void startEngine() { ... }
}

අපේ බයිසිකල් පන්තිය ද ලිස්කොව් ආදේශන මූලධර්මයට අනුකූල වේ.

class Bicycle extends DevicesWithoutEngines
{
   @Override
   void startMoving() { ... }
}

9

එල්එස්පී හි මෙම සූත්‍රගත කිරීම ඉතා ශක්තිමත් ය:

S වර්ගයේ සෑම වස්තුවක් සඳහාම T2 වර්ගයේ වස්තුවක් තිබේ නම්, සියලු වැඩසටහන් සඳහා T ට අනුව P de fi ned නම්, o1 o2 වෙනුවට ආදේශ කිරීමේදී P හි හැසිරීම නොවෙනස්ව පවතී, එවිට S යනු T හි උප ප්‍රභේදයකි.

එහි මූලික අරුත වන්නේ එස් යනු ටී හා සමාන දෙයක් මුළුමනින්ම සංවෘත ලෙස ක්‍රියාත්මක කිරීමයි. තවද මට නිර්භීත විය හැකි අතර කාර්ය සාධනය පී හි හැසිරීමේ කොටසක් බව තීරණය කළ හැකිය.

එබැවින්, මූලික වශයෙන්, ප්‍රමාද බන්ධනවල ඕනෑම භාවිතයක් එල්එස්පී උල්ලං lates නය කරයි. අප එක් වර්ගයක වස්තුවක් වෙනත් වර්ගයකට ආදේශ කරන විට වෙනස් හැසිරීමක් ලබා ගැනීම OO හි සමස්ත කරුණයි!

විකිපීඩියාව විසින් උපුටා දක්වන ලද සූත්‍රගත කිරීම වඩා හොඳ වන්නේ දේපල සන්දර්භය මත රඳා පවතින බැවින් සහ වැඩසටහනේ සමස්ත හැසිරීම අනිවාර්යයෙන්ම ඇතුළත් නොවන බැවිනි.


2
අර්ම්, එම සූත්‍රගත කිරීම බාබරා ලිස්කොව්ගේම ය. බාබරා ලිස්කොව්, “දත්ත සාරාංශ හා ධූරාවලිය,” සිග්ලන් නිවේදන, 23,5 (1988 මැයි). එය "මාර්ගය ඉතා ශක්තිමත්" නොවේ, එය "හරියටම හරි" වන අතර, එය ඇතැයි ඔබ සිතන ඇඟවුම් එයට නැත. එය ශක්තිමත් නමුත් නිවැරදි ශක්තියක් ඇත.
DrPizza

සැබෑ ජීවිතයේ උප වර්ග ඉතා ස්වල්පයක් ඇත :)
ඩේමියන් පොලට්

3
“හැසිරීම නොවෙනස්ව පවතී” යන්නෙන් අදහස් කරන්නේ උප ප්‍රභේදයක් ඔබට නිශ්චිත ප්‍රති result ල අගයක් ලබා දෙන බවයි. එහි අර්ථය වන්නේ උප වර්ගයෙහි හැසිරීම මූලික වර්ගයට අපේක්ෂිත දේට ගැලපෙන බවයි. උදාහරණය: පාදක වර්ගය හැඩයට දිනුම් () ක්‍රමයක් තිබිය හැකි අතර මෙම ක්‍රමය හැඩය ලබා දිය යුතු බවට නියම කරයි. හැඩයේ උප වර්ග දෙකක් (උදා: චතුරස්රය සහ කවය) දිනුම් ඇදීමේ ක්‍රමය ක්‍රියාත්මක කරන අතර ප්‍රති results ල වෙනස් ලෙස පෙනෙනු ඇත. නමුත් හැසිරීම (හැඩය විදැහුම් කිරීම) හැඩයේ නිශ්චිත හැසිරීමට අනුරූප වන තාක් කල්, චතුරස්රය සහ කවය එල්එස්පීයට අනුකූලව හැඩයේ උප වර්ග වේ.
ස්ටීව්

9

ඉතා සරල වාක්‍යයකින් අපට මෙසේ පැවසිය හැකිය.

ළමා පන්තිය එහි මූලික පන්ති ලක්ෂණ උල්ලං not නය නොකළ යුතුය. එය සමඟ හැකියාව තිබිය යුතුය. අපට කිව හැක්කේ එය උප වර්ගය හා සමාන බවයි.


9

ලිස්කොව්ගේ ආදේශන මූලධර්මය (එල්එස්පී)

සෑම විටම අපි වැඩසටහන් මොඩියුලයක් නිර්මාණය කරන අතර අපි පන්ති ධූරාවලියක් නිර්මාණය කරමු. ඉන්පසුව අපි ව්‍යුත්පන්න පංති කිහිපයක් නිර්මාණය කරමින් පන්ති දීර් extend කරමු.

පැරණි ව්‍යුත්පන්න පංතිවල ක්‍රියාකාරිත්වය ප්‍රතිස්ථාපනය නොකර නව ව්‍යුත්පන්න පංති විස්තාරණය වන බවට අප වග බලා ගත යුතුය. එසේ නොමැති නම්, නව පංති පවතින වැඩසටහන් මොඩියුලවල භාවිතා කරන විට අනවශ්‍ය බලපෑම් ඇති කළ හැකිය.

ලිස්කොව්ගේ ආදේශන මූලධර්මය පවසන්නේ වැඩසටහන් මොඩියුලයක් මූලික පංතියක් භාවිතා කරන්නේ නම්, වැඩසටහන් මොඩියුලයේ ක්‍රියාකාරීත්වයට කිසිදු බලපෑමක් නොකර මූලික පන්තිය පිළිබඳ සඳහන ව්‍යුත්පන්න පන්තියක් සමඟ ප්‍රතිස්ථාපනය කළ හැකි බවයි.

උදාහරණයක්:

පහත දැක්වෙන්නේ ලිස්කොව්ගේ ආදේශන මූලධර්මය උල්ලං is නය වන හොඳම උදාහරණයයි. උදාහරණයක් ලෙස, පන්ති 2 ක් භාවිතා කරයි: සෘජුකෝණාස්රය සහ චතුරස්රය. යෙදුමේ කොතැනක හෝ සෘජුකෝණාස්රාකාර වස්තුව භාවිතා කර ඇතැයි උපකල්පනය කරමු. අපි යෙදුම දිගු කර වර්ග පන්තිය එකතු කරමු. සමහර කොන්දේසි මත පදනම්ව වර්ග පන්තිය කර්මාන්තශාලා රටාවකින් ආපසු ලබා දෙන අතර කුමන ආකාරයේ වස්තුවක් ආපසු ලබා දෙනු ඇත්දැයි අපි නොදනිමු. නමුත් අපි දන්නවා එය සෘජුකෝණාස්රයක්. අපි සෘජුකෝණාස්රාකාර වස්තුව ලබා ගනිමු, පළල 5 ට සහ උස 10 ට සකසා ප්‍රදේශය ලබා ගනිමු. පළල 5 සහ උස 10 සහිත සෘජුකෝණාස්රයක් සඳහා, ප්රදේශය 50 ක් විය යුතුය. ඒ වෙනුවට, ප්රති result ලය 100 ක් වනු ඇත

    // Violation of Likov's Substitution Principle
class Rectangle {
    protected int m_width;
    protected int m_height;

    public void setWidth(int width) {
        m_width = width;
    }

    public void setHeight(int height) {
        m_height = height;
    }

    public int getWidth() {
        return m_width;
    }

    public int getHeight() {
        return m_height;
    }

    public int getArea() {
        return m_width * m_height;
    }
}

class Square extends Rectangle {
    public void setWidth(int width) {
        m_width = width;
        m_height = width;
    }

    public void setHeight(int height) {
        m_width = height;
        m_height = height;
    }

}

class LspTest {
    private static Rectangle getNewRectangle() {
        // it can be an object returned by some factory ...
        return new Square();
    }

    public static void main(String args[]) {
        Rectangle r = LspTest.getNewRectangle();

        r.setWidth(5);
        r.setHeight(10);
        // user knows that r it's a rectangle.
        // It assumes that he's able to set the width and height as for the base
        // class

        System.out.println(r.getArea());
        // now he's surprised to see that the area is 100 instead of 50.
    }
}

නිගමනය:

මෙම මූලධර්මය විවෘත වසා දැමීමේ මූලධර්මයේ දිගුවක් පමණක් වන අතර එයින් අදහස් කරන්නේ නව ව්‍යුත්පන්න පංති ඔවුන්ගේ හැසිරීම වෙනස් නොකර මූලික පන්ති පුළුල් කරන බවට අප වග බලා ගත යුතු බවයි.

මෙයද බලන්න: විවෘත වසන්න මූලධර්මය

වඩා හොඳ ව්‍යුහයක් සඳහා සමාන සංකල්ප කිහිපයක්: වින්‍යාසය පිළිබඳ සම්මුතිය


8

සමහර අතිරේකයක්:
ව්‍යුත්පන්න පංතිවලට අවනත විය යුතු මූලික පංතියේ වෙනස් නොවන, පූර්ව කොන්දේසි සහ පශ්චාත් කොන්දේසි ගැන කිසිවෙකු ලිව්වේ නැත්තේ ඇයිදැයි මම කල්පනා කරමි. ව්‍යුත්පන්න පංතිය B මූලික පන්තියෙන් සම්පූර්ණයෙන්ම ගැලවිය හැකි නම්, D පන්තිය සමහර කොන්දේසි වලට අවනත විය යුතුය:

  • පාදක පන්තියේ ප්‍රභේද ව්‍යුත්පන්න පන්තිය විසින් ආරක්ෂා කළ යුතුය
  • පාදක පන්තියේ පූර්ව කොන්දේසි ව්‍යුත්පන්න පන්තිය විසින් ශක්තිමත් නොකළ යුතුය
  • පාදක පන්තියේ පශ්චාත් කොන්දේසි ව්‍යුත්පන්න පන්තිය විසින් දුර්වල නොකළ යුතුය.

එබැවින් ව්‍යුත්පන්නය මූලික පන්තිය විසින් පනවා ඇති ඉහත කොන්දේසි තුන පිළිබඳව දැනුවත් විය යුතුය. එබැවින් උප වර්ගීකරණය කිරීමේ නීති කලින් තීරණය කර ඇත. එහි අර්ථය නම්, 'අයිඑස් ඒ' සම්බන්ධතාවයට අවනත විය යුත්තේ යම් යම් නීති රීති උප ප්‍රභේදයට අවනත වූ විට පමණි. මෙම නීති, වෙනස්වීම්, පූර්ව නිගමන සහ පශ්චාත් කොන්දේසි ලෙස විධිමත් ' සැලසුම් කොන්ත්‍රාත්තුවක් ' මගින් තීරණය කළ යුතුය .

මේ පිළිබඳ වැඩිදුර සාකච්ඡා මගේ බ්ලොග් අඩවියෙන් ලබා ගත හැකිය: ලිස්කොව් ආදේශන මූලධර්මය


8

ලිස්කොව් ආදේශන මූලධර්මය

  • අභිබවා ගිය ක්‍රමය හිස්ව නොතිබිය යුතුය
  • අභිබවා ගිය ක්‍රමය දෝෂයක් නොතැබිය යුතුය
  • ව්‍යුත්පන්න පංති හැසිරීම් නිසා මූලික පංතිය හෝ අතුරු මුහුණත් හැසිරීම වෙනස් කිරීම (නැවත වැඩ කිරීම) සඳහා නොයා යුතුය.

8

එල්එස්පී සරල වචන වලින් කියනවා එකම සුපිරි පන්තියේ වස්තූන් කිසිවක් කඩ නොකර එකිනෙකා සමඟ හුවමාරු කර ගත හැකි බව .

උදාහරණයක් ලෙස, අපි නම් Catසහ Dogක ව්යුත්පන්න පන්තියේ Animalපන්ති, සත්ව පන්ති භාවිතා කිසිදු කාර්යයක් භාවිතා කිරීමට හැකි විය යුතුය Catහෝ Dogහා සාමාන්යයෙන් හැසිරෙන.


7

මෙම මූලධර්මය 1987 දී බාබරා ලිස්කොව් විසින් හඳුන්වා දෙන ලද අතර සුපිරි පන්තියක හැසිරීම සහ එහි උප ප්‍රභේද කෙරෙහි අවධානය යොමු කරමින් විවෘත සංවෘත මූලධර්මය පුළුල් කරයි.

එය උල්ලං of නය කිරීමේ ප්‍රතිවිපාක සලකා බලන විට එහි වැදගත්කම පැහැදිලි වේ. පහත පන්තිය භාවිතා කරන යෙදුමක් සලකා බලන්න.

public class Rectangle 
{ 
  private double width;

  private double height; 

  public double Width 
  { 
    get 
    { 
      return width; 
    } 
    set 
    { 
      width = value; 
    }
  } 

  public double Height 
  { 
    get 
    { 
      return height; 
    } 
    set 
    { 
      height = value; 
    } 
  } 
}

එක් දිනක් සේවාදායකයා සෘජුකෝණාස්රා වලට අමතරව චතුරස්රයන් හැසිරවීමේ හැකියාව ඉල්ලා සිටින බව සිතන්න. චතුරස්රයක් සෘජුකෝණාස්රයක් බැවින්, වර්ග පන්තිය සෘජුකෝණාස්රා පන්තියෙන් ව්යුත්පන්න විය යුතුය.

public class Square : Rectangle
{
} 

කෙසේ වෙතත්, එසේ කිරීමෙන් අපට ගැටළු දෙකක් ඇති වේ:

හතරැස් කොටුවකට උරුම වූ උස හා පළල විචල්‍යයන් අවශ්‍ය නොවන අතර වර්ග වස්තු සිය දහස් ගණනක් නිර්මාණය කිරීමට සිදුවුවහොත් මෙය මතකයේ සැලකිය යුතු අපද්‍රව්‍යයක් නිර්මාණය කළ හැකිය. හතරැස් කොටුවෙන් පළල සහ උස සැකසීමේ ගුණාංග වර්ගයකට නුසුදුසු බැවින් වර්ගයක පළල සහ උස සමාන වේ. උස සහ පළල යන දෙකම එකම අගයකට සැකසීම සඳහා, අපට පහත පරිදි නව ගුණාංග දෙකක් නිර්මාණය කළ හැකිය:

public class Square : Rectangle
{
  public double SetWidth 
  { 
    set 
    { 
      base.Width = value; 
      base.Height = value; 
    } 
  } 

  public double SetHeight 
  { 
    set 
    { 
      base.Height = value; 
      base.Width = value; 
    } 
  } 
}

දැන්, යමෙකු හතරැස් වස්තුවක පළල සකසන විට, එහි උස ඒ අනුව සහ අනෙක් අතට වෙනස් වේ.

Square s = new Square(); 
s.SetWidth(1); // Sets width and height to 1. 
s.SetHeight(2); // sets width and height to 2. 

අපි ඉදිරියට යමු මෙම අනෙක් කාර්යය සලකා බලමු:

public void A(Rectangle r) 
{ 
  r.SetWidth(32); // calls Rectangle.SetWidth 
} 

අපි මෙම ශ්‍රිතයට වර්ග වස්තුවක් වෙත යොමු කිරීමක් කළහොත්, අපි එල්එස්පී උල්ලං would නය කරන්නේ එම ශ්‍රිතය එහි තර්කවල ව්‍යුත්පන්නයන් සඳහා ක්‍රියා නොකරන බැවිනි. ගුණාංග පළල සහ උස බහුඅවයවික නොවේ, මන්ද ඒවා සෘජුකෝණාස්රයේ අථත්‍ය ලෙස ප්‍රකාශයට පත් නොකෙරේ (උස වෙනස් නොවන නිසා වර්ග වස්තුව දූෂිත වනු ඇත).

කෙසේ වෙතත්, සැකසුම් ගුණාංග අතථ්‍ය යැයි ප්‍රකාශ කිරීමෙන් අපට තවත් උල්ලං face නය කිරීමකට මුහුණ දීමට සිදුවේ. ඇත්ත වශයෙන්ම, ව්‍යුත්පන්න පංති චතුරස්රයක් නිර්මාණය කිරීම මූලික පන්තියේ සෘජුකෝණාස්රයේ වෙනස්කම් ඇති කරයි.


5

චතුරස්රයක් යනු පළල උස හා සමාන වන සෘජුකෝණාස්රයකි. පළල සහ උස සඳහා වර්ග දෙක වෙනස් ප්‍රමාණ දෙකක් සකසන්නේ නම් එය වර්ග ආක්‍රමණ උල්ලං lates නය කරයි. අතුරු ආබාධ හඳුන්වා දීමෙන් මෙය ක්‍රියාත්මක වේ. නමුත් සෘජුකෝණාස්රයේ පූර්ව කොන්දේසිය 0 <උස සහ 0 <පළල සහිත කට්ටලයක් (උස, පළල) තිබේ නම්. ව්‍යුත්පන්න උප වර්ගයට උස == පළල අවශ්‍ය වේ; වඩා ශක්තිමත් පූර්ව කොන්දේසියක් (සහ එය lsp උල්ලං lates නය කරයි). මෙයින් පෙනී යන්නේ හතරැස් සෘජුකෝණාස්රයක් වුවද එය වලංගු උප ප්‍රභේදයක් නොවන බැවින් පූර්ව කොන්දේසිය ශක්තිමත් වන බවයි. අවට වැඩ (පොදුවේ නරක දෙයක්) අතුරු ආබාධයක් ඇති කරන අතර මෙය පශ්චාත් තත්වය දුර්වල කරයි (එය lsp උල්ලං) නය කරයි). setWidth පාදමේ 0 <පළල. ව්‍යුත්පන්නය උස == පළල සමඟ එය දුර්වල කරයි.

එබැවින් ප්‍රතිනිර්මාණය කළ හැකි චතුරස්රයක් නැවත වෙනස් කළ හැකි සෘජුකෝණාස්රයක් නොවේ.


4

පුවරු සමූහයක් අනුව ත්‍රි ඩී බෝඩ් ක්‍රියාත්මක කිරීම එතරම් ප්‍රයෝජනවත් වේද?

සමහර විට ඔබට විවිධ ගුවන් යානා වල ත්රී ඩී බෝඩ් පෙති මණ්ඩලයක් ලෙස සැලකීමට අවශ්ය විය හැකිය. එවැනි අවස්ථාවකදී ඔබට මණ්ඩලය සඳහා බහු අතුරු මුහුණතක් (හෝ වියුක්ත පන්තියක්) සාරාංශ කිරීමට අවශ්‍ය විය හැකිය.

බාහිර අතුරුමුහුණත සම්බන්ධයෙන් ගත් කල, ඔබට TwoDBoard සහ ThreeDBoard යන දෙකටම පුවරු අතුරුමුහුණතක් ඉදිරිපත් කිරීමට අවශ්‍ය විය හැකිය (ඉහත ක්‍රම කිසිවක් නොගැලපේ).


1
ත්‍රි ඩී බෝඩ් සන්දර්භය තුළ පුවරුවෙන් උරුම වීම අර්ථවත් නොවන බව පෙන්වීමට උදාහරණය සරල යැයි මම සිතමි. සියලුම අත්සන ඉසෙඩ් අක්ෂයකින් අර්ථ විරහිත ය.
NotMyself

3

එල්එස්පී සඳහා මා මෙතෙක් සොයාගෙන ඇති පැහැදිලි පැහැදිලි කිරීම නම් “ලිස්කොව් ආදේශන මූලධර්මය පවසන්නේ ව්‍යුත්පන්න පන්තියක වස්තුවට පද්ධතියේ කිසිදු දෝෂයක් ගෙන ඒමට හෝ මූලික පන්තියේ හැසිරීම වෙනස් නොකර මූලික පන්තියේ වස්තුවක් ප්‍රතිස්ථාපනය කිරීමට හැකි විය යුතු බවයි. " මෙතනින් . එල්එස්පී උල්ලං ting නය කිරීම සහ එය නිවැරදි කිරීම සඳහා ලිපිය කේත උදාහරණයක් සපයයි.


1
කරුණාකර ස්ටක් ඕවර් ප්‍රවාහයේ කේතයේ උදාහරණ සපයන්න.
සෙබෙනලර්න්

3

අපි අපේ කේතයේ සෘජුකෝණාස්රයක් භාවිතා කරමු

r = new Rectangle();
// ...
r.setDimensions(1,2);
r.fill(colors.red());
canvas.draw(r);

අපගේ ජ්‍යාමිති පන්තියේදී අපි දැනගත්තේ චතුරස්රයක් යනු විශේෂ සෘජුකෝණාස්රයක් වන බැවින් එහි පළල එහි උස හා සමාන දිගක් වන බැවිනි. Squareමෙම තොරතුරු මත පදනම්ව අපි පන්තියක් කරමු :

class Square extends Rectangle {
    setDimensions(width, height){
        assert(width == height);
        super.setDimensions(width, height);
    }
} 

අපගේ පළමු කේතය Rectangleසමඟ අපි එය ප්‍රතිස්ථාපනය කළහොත් Squareඑය බිඳී යනු ඇත:

r = new Square();
// ...
r.setDimensions(1,2); // assertion width == height failed
r.fill(colors.red());
canvas.draw(r);

මෙයට හේතුව පන්තියේ Squareඅප සතුව නොතිබූ නව පූර්ව කොන්දේසියක් තිබීමයි Rectangle: width == height. එල්එස්පීයට අනුව, උප පංති අවස්ථා Rectangleසමඟ ආදේශ කළ යුතුය Rectangle. මෙයට හේතුව මෙම සිද්ධීන් නිදසුන් සඳහා වන වර්ගයේ චෙක්පත පසු කරන Rectangleඅතර එමඟින් ඔබේ කේතයේ අනපේක්ෂිත දෝෂ ඇති වේ.

මේ සඳහා උදාහරණයක් ලෙස ඔහු "පූර්ව කොන්දේසි ඇති subtype ශක්තිමත් කළ නොහැක" මෙම ප්රදේශයේ දී , විකි ලිපිය . සාරාංශයක් ලෙස, එල්එස්පී උල්ලං ting නය කිරීම සමහර විට ඔබේ කේතයේ දෝෂ ඇති කරයි.


3

එල්එස්පී පවසන්නේ වස්තූන් ඒවායේ උප ප්‍රභේද මගින් ප්‍රතිස්ථාපනය කළ යුතු බවයි. අනෙක් අතට, මෙම මූලධර්මය පෙන්වා දෙයි

ළමා පන්ති කිසි විටෙකත් මව් පන්තියේ අර්ථ දැක්වීම් කඩ නොකළ යුතුය.

එල්එස්පී පිළිබඳ වඩා හොඳ අවබෝධයක් ලබා ගැනීමට පහත උදාහරණය උපකාරී වේ.

එල්එස්පී නොමැතිව:

public interface CustomerLayout{

    public void render();
}


public FreeCustomer implements CustomerLayout {
     ...
    @Override
    public void render(){
        //code
    }
}


public PremiumCustomer implements CustomerLayout{
    ...
    @Override
    public void render(){
        if(!hasSeenAd)
            return; //it isn`t rendered in this case
        //code
    }
}

public void renderView(CustomerLayout layout){
    layout.render();
}

එල්එස්පී විසින් සවි කිරීම:

public interface CustomerLayout{
    public void render();
}


public FreeCustomer implements CustomerLayout {
     ...
    @Override
    public void render(){
        //code
    }
}


public PremiumCustomer implements CustomerLayout{
    ...
    @Override
    public void render(){
        if(!hasSeenAd)
            showAd();//it has a specific behavior based on its requirement
        //code
    }
}

public void renderView(CustomerLayout layout){
    layout.render();
}

2

ලිපිය කියවීමට මම ඔබව දිරිමත් කරමි: ලිස්කොව් ආදේශන මූලධර්මය (එල්එස්පී) උල්ලං ting නය කිරීම .

ලිස්කොව් ආදේශන මූලධර්මය යනු කුමක්ද යන්න පැහැදිලි කිරීමක් ඔබට සොයාගත හැකිය, ඔබ දැනටමත් එය උල්ලං has නය කර ඇත්දැයි අනුමාන කිරීමට උපකාරී වන සාමාන්‍ය ඉඟි සහ ඔබේ පන්ති ධූරාවලිය වඩාත් ආරක්ෂිත කිරීමට ඔබට උපකාරී වන ප්‍රවේශයේ උදාහරණයක්.


2

LISKOV SUBSTITUTION PRINCIPLE (මාර්ක් සීමන් පොතෙන්) සඳහන් කරන්නේ සේවාදායකයා හෝ ක්‍රියාත්මක කිරීම නොකොට අතුරු මුහුණතක එක් ක්‍රියාත්මක කිරීමක් වෙනත් එකක් සමඟ ප්‍රතිස්ථාපනය කිරීමට අපට හැකි විය යුතු බවයි. මෙම මූලධර්මය මඟින් අනාගතයේදී සිදුවන අවශ්‍යතා සපුරාලීමට අපට හැකි වුවද, අද ඒවා පුරෝකථනය නොකරන්න.

අපි පරිගණකය බිත්තියෙන් ඉවත් කළහොත් (ක්‍රියාත්මක කිරීම), බිත්ති දොරටුව (අතුරුමුහුණත) හෝ පරිගණකය (සේවාදායකයා) බිඳ වැටෙන්නේ නැත (ඇත්ත වශයෙන්ම එය ලැප්ටොප් පරිගණකයක් නම්, එය යම් කාලයක් සඳහා එහි බැටරි මත පවා ධාවනය කළ හැකිය) . කෙසේ වෙතත්, මෘදුකාංග සමඟ, සේවාදායකයෙකු බොහෝ විට සේවාවක් ලබා ගැනීමට අපේක්ෂා කරයි. සේවාව ඉවත් කර ඇත්නම්, අපට NullReferenceException එකක් ලැබේ. මෙවැනි තත්වයන්ට මුහුණ දීම සඳහා අපට “කිසිවක්” නොකරන අතුරු මුහුණතක් ක්‍රියාත්මක කළ හැකිය. මෙය Null Object ලෙස හැඳින්වෙන මෝස්තර රටාවකි, [4] එය දළ වශයෙන් පරිගණකය බිත්තියෙන් ඉවත් කිරීමට අනුරූප වේ. අප ලිහිල් කප්ලිං භාවිතා කරන නිසා, අපට සැබෑ ක්‍රියාවලියක් කරදරයකින් තොරව කිසිවක් නොකරන දෙයක් සමඟ ප්‍රතිස්ථාපනය කළ හැකිය.


2

ලිකොව්ගේ ආදේශන මූලධර්මය පවසන්නේ වැඩසටහන් මොඩියුලයක් මූලික පන්තියක් භාවිතා කරන්නේ නම්, වැඩසටහන් මොඩියුලයේ ක්‍රියාකාරීත්වයට කිසිදු බලපෑමක් නොකර මූලික පන්තිය පිළිබඳ සඳහන ව්‍යුත්පන්න පන්තියක් සමඟ ප්‍රතිස්ථාපනය කළ හැකි බවයි.

අභිප්‍රාය - ව්‍යුත්පන්න වර්ග ඒවායේ මූලික වර්ග සඳහා සම්පූර්ණයෙන්ම ආදේශ කළ යුතුය.

උදාහරණය - ජාවා හි සම-විචල්‍ය ප්‍රතිලාභ වර්ග.


1

මෙන්න මේ පෝස්ට් එකෙන් උපුටා ගත් කොටසක් කාරණා මනාව පැහැදිලි කරයි:

[..] සමහර මූලධර්ම අවබෝධ කර ගැනීම සඳහා, එය උල්ලං has නය වූ විට එය වටහා ගැනීම වැදගත්ය. මෙය මම දැන් කරන්නෙමි.

මෙම මූලධර්මය උල්ලං violation නය කිරීම යන්නෙන් අදහස් කරන්නේ කුමක්ද? එයින් ගම්‍ය වන්නේ වස්තුවක් අතුරුමුහුණතක් සමඟ ප්‍රකාශිත සාරාංශයක් මගින් පනවන ලද කොන්ත්‍රාත්තුව ඉටු නොකරන බවයි. වෙනත් වචන වලින් කිවහොත්, එයින් අදහස් වන්නේ ඔබ ඔබේ සාරාංශ වැරදි ලෙස හඳුනාගෙන ඇති බවයි.

පහත උදාහරණය සලකා බලන්න:

interface Account
{
    /**
     * Withdraw $money amount from this account.
     *
     * @param Money $money
     * @return mixed
     */
    public function withdraw(Money $money);
}
class DefaultAccount implements Account
{
    private $balance;
    public function withdraw(Money $money)
    {
        if (!$this->enoughMoney($money)) {
            return;
        }
        $this->balance->subtract($money);
    }
}

මෙය එල්එස්පී උල්ලං is නය කිරීමක්ද? ඔව්. මෙයට හේතුව ගිණුමේ මුදල් ආපසු ගන්නා බව ගිණුමේ කොන්ත්‍රාත්තුව අපට පවසන නමුත් මෙය සැමවිටම එසේ නොවේ. එබැවින්, එය නිවැරදි කිරීම සඳහා මා කුමක් කළ යුතුද? මම දැන් කොන්ත්රාත්තුව වෙනස් කරමි:

interface Account
{
    /**
     * Withdraw $money amount from this account if its balance is enough.
     * Otherwise do nothing.
     *
     * @param Money $money
     * @return mixed
     */
    public function withdraw(Money $money);
}

Voilà, දැන් කොන්ත්රාත්තුව සෑහීමකට පත්වේ.

මෙම සියුම් උල්ලං violation නය කිරීම බොහෝ විට සේවාදායකයකු විසින් භාවිතා කරනු ලබන කොන්ක්‍රීට් වස්තූන් අතර වෙනස පැවසීමේ හැකියාව ඇත. උදාහරණයක් ලෙස, පළමු ගිණුමේ කොන්ත්‍රාත්තුව අනුව, එය පහත පරිදි විය හැකිය:

class Client
{
    public function go(Account $account, Money $money)
    {
        if ($account instanceof DefaultAccount && !$account->hasEnoughMoney($money)) {
            return;
        }
        $account->withdraw($money);
    }
}

තවද, මෙය ස්වයංක්‍රීයව විවෘත සංවෘත මූලධර්මය උල්ලං lates නය කරයි [එනම් මුදල් ආපසු ගැනීමේ අවශ්‍යතාවය සඳහා. කොන්ත්රාත්තුව උල්ලං ting නය කරන වස්තුවකට ප්රමාණවත් මුදලක් නොමැති නම් කුමක් සිදුවේදැයි ඔබ කිසි විටෙකත් නොදන්නා බැවිනි. බොහෝ විට එය කිසිවක් ආපසු නොදෙනු ඇත, බොහෝ විට ව්යතිරේකයක් විසි කරනු ඇත. එබැවින් ඔබ එය පරික්ෂා කළ යුතුය hasEnoughMoney()- එය අතුරු මුහුණතක කොටසක් නොවේ. එබැවින් මෙම බලහත්කාරයෙන් කොන්ක්‍රීට් පන්තිය මත යැපෙන චෙක්පත OCP උල්ලං is නය කිරීමකි].

එල්එස්පී උල්ලං about නය කිරීම පිළිබඳව මා නිතර නිතර මුණගැසෙන වැරදි මතයකට මෙම කරුණ ආමන්ත්‍රණය කරයි. එහි සඳහන් වන්නේ “දරුවෙකු තුළ දෙමව්පියන්ගේ හැසිරීම වෙනස් වූයේ නම් එය එල්එස්පී උල්ලං lates නය කරයි.” කෙසේ වෙතත්, එය එසේ නොවේ - දරුවෙකු තම දෙමව්පියන්ගේ කොන්ත්‍රාත්තුව උල්ලං does නය නොකරන තාක් කල්.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.