Liskov Substitution Principle in C#

Th? Liskov Substitution Principl? (LSP) is one of th? fiv? SOLID principl?s of obj?ct-ori?nt?d programming and d?sign. It was introduced by Barbara Liskov in 1987 and is specifically d?sign?d to guid? th? inh?ritanc? and polymorphism aspects of obj?ct-ori?nt?d programming. In C# and oth?r obj?ct-ori?nt?d languag?s, th? Liskov Substitution Principl? is a fundam?ntal guid?lin? for writing and using class?s and inh?ritanc? hi?rarchi?s.

Th? Liskov Substitution Principl? can b? stat?d as follows:

"Subtyp?s must b? substitutabl? for th?ir bas? typ?s without alt?ring th? corr?ctn?ss of th? program".

It means that if you have a bas? class and a d?riv?d class, obj?cts of th? d?riv?d class should b? abl? to r?plac? obj?cts of th? bas? class without causing any un?xp?ct?d b?havior or violating th? invariants of th? program. In C#, you oft?n s?? this principl? appli?d to inh?ritanc? and polymorphism, wh?r? d?riv?d class?s ar? ?xp?ct?d to adh?r? to th? sam? contract (int?rfac?) as th?ir bas? class?s.

H?r? ar? som? k?y points to und?rstand about th? Liskov Substitution Principl? in C#:

Inh?ritanc? Hi?rarchy: In C#, th? LSP is primarily conc?rn?d with th? r?lationship b?tw??n a bas? class and its d?riv?d class?s. D?riv?d class?s should ?xt?nd and sp?cializ? th? behavior of th? bas? class whil? maintaining th? sam? int?rfac? (m?thods and prop?rti?s).

M?thod Signatur?s: M?thods in d?riv?d class?s should hav? th? sam? m?thod signatur?s as thos? in th? bas? class. It means th? d?riv?d class can ov?rrid? or ?xt?nd th? behavior of th? bas? class m?thods, but it must not change th? m?thod's nam?, param?t?rs, and r?turn typ?s.

Postconditions: A d?riv?d class should m??t or r?lax th? postconditions (?xp?ct?d behavior) of th? bas? class m?thods. It should not w?ak?n or violat? th?s? conditions. In other words, a d?riv?d class can mak? its m?thods mor? p?rmissiv? but not mor? r?strictiv?.

Pr?conditions: A d?riv?d class should str?ngth?n or maintain th? pr?conditions (r?quir?d conditions) of th? bas? class m?thods. It should not loos?n th?s? pr?conditions. It ?nsur?s that any cod? r?lying on th? bas? class int?rfac? will still work corr?ctly with obj?cts of th? d?riv?d class.

Exc?ptions: If th? bas? class m?thod throws ?xc?ptions und?r c?rtain conditions, th? d?riv?d class can throw th? sam? ?xc?ptions or mor? sp?cific ?xc?ptions. It should not throw broad?r or un?xp?ct?d ?xc?ptions.

How to use Liskov Substitution Principl? in C#:

If you want to us? th? Liskov Substitution Principl? (LSP) ?ff?ctiv?ly in C#, follow th?s? guid?lin?s and b?st practic?s:

D?sign a Common Bas? Class or Int?rfac?:

Start by d?signing a bas? class or int?rfac? that d?fin?s a s?t of m?thods and prop?rti?s shar?d by all d?riv?d class?s. This common bas? class or int?rfac? r?pr?s?nts th? contract that all d?riv?d class?s must adh?r? to.

Ov?rrid? or Impl?m?nt M?thods Appropriat?ly:

In d?riv?d class?s, ov?rrid? or impl?m?nt th? m?thods and prop?rti?s d?fin?d in th? bas? class or int?rfac? as n??d?d. Ensur? that th? behavior of th?s? m?thods r?sp?cts th? ?xp?ctations s?t by th? bas? class or int?rfac?.

Maintain th? Sam? M?thod Signatur?s:

In d?riv?d class?s, th? m?thod signatur?s (m?thod nam?, param?t?rs, and r?turn typ?) should b? th? sam? as thos? in th? bas? class or int?rfac?. It ?nsur?s that obj?cts of d?riv?d class?s can b? us?d int?rchang?ably with obj?cts of th? bas? class.

Follow Postconditions and Pr?conditions:

Mak? sur? that th? postconditions (?xp?ct?d b?havior) of ov?rridd?n m?thods in d?riv?d class?s ar? at l?ast as strong as thos? of th? bas? class. In other words, d?riv?d class?s should m??t or r?lax th? sam? conditions.

Maintain or str?ngth?n th? pr?conditions (r?quir?d conditions) of th? bas? class m?thods in d?riv?d class?s. D?riv?d class?s should not loos?n th?s? pr?conditions.

Avoid Using th? "n?w" K?yword Unn?c?ssarily:

In C#, th? "n?w" k?yword can b? us?d to shadow or hid? a m?thod or prop?rty in a d?riv?d class. Use this word judiciously, as it can lead to confusion and un?xp?ct?d behavior if not used carefully. In most cases, it's b?tt?r to ov?rrid? m?thods instead of shadowing th?m.

T?st Polymorphism:

T?st th? cod? for polymorphism by cr?ating instanc?s of both th? bas? class and d?riv?d class?s and using th?m int?rchang?ably. Ensur? that th? behavior of th? d?riv?d class?s r?mains consistent with th? bas? class contract.

Docum?nt Your D?sign:

Cl?arly docum?nt th? bas? class or int?rfac? and provid? guid?lin?s for how d?riv?d class?s should impl?m?nt th?ir m?thods. This documentation is important for maintaining a shar?d understanding among d?v?lop?rs.

R?gularly R?vi?w and R?factor:

R?gularly r?vi?w th? cod?bas? to ?nsur? that d?riv?d class?s still adh?r? to th? bas? class contract. Suppose chang?s or updat?s ar? n??d?d, r?factor th? cod? to maintain consist?ncy.

Exampl?:

Let's take an example to demonstrate the use of Liskov Substitution Principl? in C#:

Output:

Ar?a of th? circl?: 78.5398163397448
Ar?a of th? r?ctangl?: 24

Explanation:

  • In this example, w? d?fin? a bas? class Shap? with a virtual m?thod Ar?a(), which calculat?s th? ar?a of a g?om?tric shap?. By d?fault, it r?turns 0, but d?riv?d class?s can ov?rrid? this m?thod to provid? specific impl?m?ntations.
  • W? cr?at? a d?riv?d class Circl? that inh?rits from Shap?. It introduc?s an additional prop?rty Radius and ov?rrid?s th? Ar?a() m?thod to calculat? th? ar?a of a circl? using th? formula πr².
  • Similarly, w? cr?at? anoth?r d?riv?d class R?ctangl? that inh?rits from Shap?. It introduc?s prop?rti?s Width and height and ov?rrid?s th? Ar?a() m?thod to calculat? th? ar?a of a r?ctangl? using th? formula width * height.
  • In th? Main m?thod, w? d?monstrat? th? Liskov Substitution Principl?:
  • W? cr?at? an obj?ct of th? Circl? class and s?t its Radius prop?rty to 5.
  • W? cr?at? an obj?ct of th? R?ctangl? class and s?t its Width to 4 and height to 6.
  • After that, w? calls th? Ar?a() m?thod on both obj?cts, which works int?rchang?ably b?caus? of polymorphism and adh?r?nc? to th? Liskov Substitution Principl?.
  • Finally, w? print th? calculat?d ar?as of th? circl? and th? r?ctangl? using Consol?.Writ?Lin?().

H?r?'s th? ?xplanation in a mor? structur?d form:

  • Th? Shap? class s?rv?s as a bas? class for various g?om?tric shap?s. It d?fin?s a virtual Ar?a() m?thod that r?turns 0 by d?fault.
  • Th? Circl? class is a specific shap? (a circl?) that d?riv?s from Shap?. It ov?rrid?s th? Ar?a() m?thod to calculat? th? ar?a bas?d on th? radius provid?d.
  • Th? R?ctangl? class is another specific shap? (a r?ctangl?) that also d?riv?s from Shap?. It ov?rrid?s th? Ar?a() m?thod to calculat? th? ar?a bas?d on th? width and height.
  • In th? Main m?thod, w? cr?at? instanc?s of Circl? and R?ctangl? and s?t th?ir sp?cific prop?rti?s (Radius and Width/height).
  • After that, w? call th? Ar?a() m?thod on th?s? obj?cts, and due to polymorphism and adh?r?nc? to th? Liskov Substitution Principl?, th? appropriat? ov?rridd?n m?thod is ?x?cut?d for ?ach obj?ct, corr?ctly calculating and r?turning th? ar?a.
  • Th? calculat?d ar?as ar? print?d to th? consol?, d?monstrating th? Liskov Substitution Principl? by substituting d?riv?d obj?cts (Circl? and R?ctangl?) for th? bas? class (Shap?) without alt?ring th? corr?ctn?ss of th? program.

Compl?xity Analysis:

Tim? Compl?xity:

  • Cr?ating th? obj?cts circl? and r?ctangl? involv?s minimal tim? compl?xity and is usually consid?r?d O(1), as it does not d?p?nd on th? siz? of data structure or any loops.
  • Calling th? Ar?a() m?thod on th?s? obj?cts also has minimal compl?xity. In this sp?cific cont?xt, it d?p?nds on th? impl?m?ntation of th? Ar?a() m?thod for ?ach class, but it g?n?rally involv?s basic arithm?tic op?rations. So, it has O(1) time complexity for both th? Circl? and R?ctangl? class?s.
  • Printing th? results with Consol?.Writ?Lin?() is also typically O(1), as it doesn't scal? with input siz?.
  • Ov?rall, th? tim? compl?xity of this cod? is O(1) or constant tim?. Th? ?x?cution tim? do?sn't d?p?nd on th? siz? of any data structur?s or th? input siz?.

Spac? Compl?xity:

  • Cr?ating obj?cts circl? and r?ctangl? consum?s m?mory to stor? th?ir prop?rti?s (Radius, Width, and height) and r?f?r?nc?s. Th? spac? r?quir?d is proportional to th? numb?r of obj?ct prop?rti?s, but it doesn't d?p?nd on th? input siz?. So, it has O(1) space complexity.
  • Calling th? Ar?a() m?thod doesn't hav? any significant impact on spac? compl?xity sinc? it primarily involv?s calculations without additional m?mory allocations.
  • Th? Consol?.Writ?Lin?() stat?m?nts don't consum? ?xtra spac? that scal?s with th? input. Th? spac? n??d?d for printing is usually small and constant, making it O(1).
  • In summary, the spac? compl?xity of this cod? is also O(1) or constant spac?. It doesn't d?p?nd on th? siz? of input data or any data structur?s.

Exampl?:

Let's take an example to calculate the area of circle and rectangle without using the Liskov Substitution Principl? in C#:

Output:

Ar?a of th? circl?: 0
Ar?a of th? r?ctangl?: 0

Explanation:

  • In this example, w? hav? a bas? class, Shap?, that d?fin?s a m?thod Ar?a() r?turning 0. Th? Ar?a m?thod is not d?clar?d as virtual or abstract, so it cannot b? ov?rridd?n by d?riv?d class?s.
  • After that, two d?riv?d class?s, Circl? and R?ctangl?, inh?rit from Shap?. How?v?r, th?y introduc? th?ir own Ar?a() m?thods using th? n?w k?yword. It ?ff?ctiv?ly hid?s th? Ar?a() m?thod of th? bas? class rather than ov?rriding it. It means that Circl? and R?ctangl? have their own Ar?a m?thods s?parat? from th? bas? class.
  • In th? Main m?thod, w? cr?at? instanc?s of Circl? and R?ctangl? and assign th?m to Shap? r?f?r?nc?s (circl? and r?ctangl?). It is allow?d b?caus? d?riv?d class?s can b? assign?d to bas? class r?f?r?nc?s.
  • Wh?n w? call th? Ar?a() m?thod on circl? and r?ctangl?, th? b?havior is d?t?rmin?d by th? typ? of th? r?f?r?nc? variabl?, not th? actual typ? of th? obj?ct. In this case, th? n?w k?yword caus?s th? bas? class's m?thod to b? invok?d, not th? ov?rridd?n m?thods in Circl? and R?ctangl?. It r?sults in th? incorr?ct behavior b?caus? th? bas? class Ar?a() m?thod always r?turns 0.
  • W? print th? ar?as of th? circl? and th? r?ctangl? to th? consol?, but th? valu?s will b? 0 for both, as th? Ar?a() m?thod of th? bas? class is invok?d.
  • In summary, this cod? d?monstrat?s how using th? n?w k?yword in th? d?riv?d class?s (Circl? and R?ctangl?) caus?s th? bas? class m?thod to b? hidd?n and not ov?rridd?n. It l?ads to un?xp?ct?d and incorr?ct behavior wh?n obj?cts of d?riv?d class?s ar? us?d through bas? class r?f?r?nc?s. It's an ?xampl? of not adh?ring to th? Liskov Substitution Principl?, which r?comm?nds that d?riv?d class?s should ?xt?nd and not hid? th? b?havior of th? bas? class.

Compl?xity Analysis:

Tim? compl?xity:

The tim? compl?xity of this cod? is O(1) or constant tim?. Th? ?x?cution tim? do?sn't d?p?nd on th? siz? of any data structur?s or th? input siz?.

Spac? compl?xity:

The spac? compl?xity of this cod? is also O(1) or constant spac?, just lik? th? Liskov Substitution Principl?-adh?ring cod?.

Th? tim? and spac? compl?xiti?s of th? cod? that do?s not adh?r? to th? Liskov Substitution Principl? ar? both O(1), m?aning th?y ar? constant and do not d?p?nd on th? input siz? or data structur?s. It is b?caus? th? fundam?ntal structur? and op?rations of th? cod?, such as obj?ct cr?ation, m?thod calls, and consol? output, do not scal? with input siz? and involv? basic arithm?tic and m?mory manag?m?nt.

R?al tim? Applications:

H?r? ar? som? r?al-tim? applications or sc?narios wh?r? th? Liskov Substitution Principl? (LSP) is applied in softwar? d?sign.

G?om?tric Shap?s:

In graphic d?sign and comput?r-aid?d d?sign (CAD) softwar?, various g?om?tric shap?s lik? circl?s, r?ctangl?s, triangl?s, and polygons can b? manipulat?d and r?nd?r?d. Th?s? shap?s adh?r? to a common g?om?tric shap? int?rfac? or bas? class.

Th? LSP allows softwar? to handl? th?s? diff?r?nt shap?s uniformly, making it ?asy to perform op?rations lik? scaling, rotation, and r?nd?ring.

Banking Syst?ms:

Banking softwar? contains various types of accounts, such as savings accounts, ch?cking accounts, and credit card accounts, as d?riv?d class?s of a common bas? account class.

Th? LSP ?nsur?s that transactions, account manag?m?nt, and int?r?st calculations can b? handl?d uniformly, making it ?asi?r to add n?w account typ?s in th? futur?.

V?hicl? Manag?m?nt:

Transportation and logistics softwar? oft?n d?al with different typ?s of v?hicl?s, including cars, trucks, bicycl?s, and motorcycl?s.

Th?s? v?hicl? typ?s adh?r? to a common v?hicl? int?rfac? or bas? class, allowing softwar? to manag? asp?cts lik? tracking, fu?l consumption, and maint?nanc? in a consist?nt mann?r.

Robotics:

In robotics, there are different types of robots, such as dron?s, humanoid robots, and industrial robots.

Th?s? robots adh?r? to a unifi?d robot control int?rfac?, ?nabling tasks lik? motion planning, path following, and s?nsor data proc?ssing to b? appli?d consist?ntly across diff?r?nt robot typ?s.






Latest Courses