<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mahi</title>
    <description>The latest articles on DEV Community by Mahi (@mahime).</description>
    <link>https://dev.to/mahime</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2736671%2F81334a64-e10d-4e6a-b5a4-08a8c2f7a3fb.png</url>
      <title>DEV Community: Mahi</title>
      <link>https://dev.to/mahime</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mahime"/>
    <language>en</language>
    <item>
      <title>Numeral systems explained (binary, octal, hexadecimal...)</title>
      <dc:creator>Mahi</dc:creator>
      <pubDate>Fri, 24 Jan 2025 11:46:34 +0000</pubDate>
      <link>https://dev.to/mahime/numeral-systems-explained-binary-octal-hexadecimal-1g5i</link>
      <guid>https://dev.to/mahime/numeral-systems-explained-binary-octal-hexadecimal-1g5i</guid>
      <description>&lt;p&gt;The most basic way of counting happens in an &lt;em&gt;unary&lt;/em&gt; numeral system, where you add a new symbol for every new item. You're already familiar with it, it's what we teach children:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🍎 apple
🍎🍎 apples
🍎🍎🍎 apples
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, writing large numbers in this manner would be more than troublesome, so us humans have invented alternative numeral systems where one symbol can be used to represent a larger quantity of items.&lt;/p&gt;

&lt;p&gt;The most common of these systems is the &lt;em&gt;decimal&lt;/em&gt; numeral system in base-10, where digits &lt;code&gt;0&lt;/code&gt; through &lt;code&gt;9&lt;/code&gt; represent a particular quantity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 =
1 = 🍎
2 = 🍎🍎
...
9 = 🍎🍎🍎🍎🍎🍎🍎🍎🍎
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The method for counting upwards in our decimal system works in the following way:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;increment the rightmost digit by one until it reaches its maximum value of &lt;code&gt;9&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;at which point reset it to its lowest value of &lt;code&gt;0&lt;/code&gt; and increment the digit to its left by one.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="mi"&gt;8&lt;/span&gt;
  &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="c1"&gt;// (1) Rightmost digit reached its maximum value of 9&lt;/span&gt;
 &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="c1"&gt;// (2) Reset it to 0 and increment the digit to its left&lt;/span&gt;
 &lt;span class="mi"&gt;11&lt;/span&gt;
 &lt;span class="mi"&gt;12&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
 &lt;span class="mi"&gt;98&lt;/span&gt;
 &lt;span class="mi"&gt;99&lt;/span&gt; &lt;span class="c1"&gt;// (1) Both rightmost and the one next to it reached maximum&lt;/span&gt;
&lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="c1"&gt;// (2) Reset to 0 and increment the digit to their left&lt;/span&gt;
&lt;span class="mi"&gt;101&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how the unary system works as well, except the maximum, the minimum, and the &lt;em&gt;only&lt;/em&gt; available digit is &lt;code&gt;1&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;dec&lt;/span&gt;   &lt;span class="n"&gt;unary&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;    &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;// (1) Rightmost digit reached its maximum value of 1&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="mi"&gt;11&lt;/span&gt; &lt;span class="c1"&gt;// (2) Reset it to 1 and increment the digit to its left&lt;/span&gt;
  &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="mi"&gt;111&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1111&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And yes, &lt;a href="https://en.wikipedia.org/wiki/Unary_numeral_system" rel="noopener noreferrer"&gt;there is no zero in unary&lt;/a&gt;—you don't have "0 🍎", you just don't have anything at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Binary and Hexadecimal
&lt;/h2&gt;

&lt;p&gt;Counting in the &lt;em&gt;binary&lt;/em&gt; (base-2) numeral system works exactly the same way, except any one digit has &lt;em&gt;two&lt;/em&gt; possible values, typically represented by &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;dec&lt;/span&gt;   &lt;span class="nx"&gt;binary&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;// (1) Rightmost digit reached its maximum value of 1&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="c1"&gt;// (2) Reset it to 0 and increment the digit to its left&lt;/span&gt;
  &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="mi"&gt;11&lt;/span&gt; &lt;span class="c1"&gt;// (1) Both rightmost and the one next to it reached maximum&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="c1"&gt;// (2) Reset to 0 and increment the digit to their left&lt;/span&gt;
  &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;
  &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;110&lt;/span&gt;
  &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;111&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now with &lt;em&gt;hexadecimal&lt;/em&gt; system being base-16—and therefore supporting more values per digit than our decimal system—we need new symbols to represent the values &lt;code&gt;10&lt;/code&gt; through &lt;code&gt;15&lt;/code&gt;. Most commonly the letters &lt;code&gt;A&lt;/code&gt; through &lt;code&gt;F&lt;/code&gt; are used respectively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;dec&lt;/span&gt;   &lt;span class="nx"&gt;hexa&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="mi"&gt;2&lt;/span&gt;
   &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="mi"&gt;9&lt;/span&gt;
 &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="nx"&gt;A&lt;/span&gt;
 &lt;span class="mi"&gt;11&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="nx"&gt;B&lt;/span&gt;
 &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="nx"&gt;C&lt;/span&gt;
 &lt;span class="mi"&gt;13&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="nx"&gt;D&lt;/span&gt;
 &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="nx"&gt;E&lt;/span&gt;
 &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;   &lt;span class="nx"&gt;F&lt;/span&gt; &lt;span class="c1"&gt;// (1) Rightmost digit reached its maximum value of F&lt;/span&gt;
 &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="c1"&gt;// (2) Reset it to 0 and increment the digit to its left&lt;/span&gt;
 &lt;span class="mi"&gt;17&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="mi"&gt;11&lt;/span&gt;
   &lt;span class="p"&gt;...&lt;/span&gt;
 &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;E&lt;/span&gt;
 &lt;span class="mi"&gt;31&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;F&lt;/span&gt; &lt;span class="c1"&gt;// (1) Rightmost digit reached its maximum value of F&lt;/span&gt;
 &lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="c1"&gt;// (2) Reset it to 0 and increment the digit to its left&lt;/span&gt;
 &lt;span class="mi"&gt;33&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="mi"&gt;21&lt;/span&gt;
   &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="mi"&gt;254&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nx"&gt;FE&lt;/span&gt;
&lt;span class="mi"&gt;255&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nx"&gt;FF&lt;/span&gt; &lt;span class="c1"&gt;// (1) Both rightmost and the one next to it reached maximum&lt;/span&gt;
&lt;span class="mi"&gt;256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="c1"&gt;// (2) Reset to 0 and increment the digit to their left&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, counting in &lt;em&gt;any&lt;/em&gt; numeral system works exactly the same way, only the number of different quantities representable by any one symbol changes. This is basically what "base-n" means, with &lt;code&gt;n&lt;/code&gt; being the number of options representable by one digit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repetition is the mother of learning
&lt;/h2&gt;

&lt;p&gt;Notice that these numeral systems are nothing more but a &lt;em&gt;visual representation&lt;/em&gt; of the underlying value, in other words the number of apples stays exactly the same:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkv7a5aocj8fkh2y8h57x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkv7a5aocj8fkh2y8h57x.png" alt="Counting in different numeric systems" width="673" height="683"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are other commonly used numeral systems as well, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;base-60 used between hours and minutes or minutes and seconds in a clock,&lt;/li&gt;
&lt;li&gt;base-12 used for months in a year or hours in the AM/PM system, or&lt;/li&gt;
&lt;li&gt;base-7 used for days in a week.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why so many systems?
&lt;/h2&gt;

&lt;p&gt;Arguably the real world is closest represented by the unary numeral system, where having three apples is just having 🍎🍎🍎 and nothing more. But us humans typically find the decimal system easier to work with, simply due to how repetitive and troublesome it would be to write in unary.&lt;/p&gt;

&lt;p&gt;However, for most computers the binary system is the &lt;em&gt;only&lt;/em&gt; available option, as the transistors inside their electronic parts can only represent two states: ON or OFF, &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;0&lt;/code&gt;. This is why us programmers often need to understand various numeral systems well.&lt;/p&gt;

&lt;p&gt;Systems like octal (base-8) and hexadecimal (base-16) are mostly used by humans in the context of programming and computer data, where writing out the individual bits of a number would be too troublesome:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;hex&lt;/span&gt;  &lt;span class="nx"&gt;binary&lt;/span&gt;
 &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0000&lt;/span&gt;
 &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0001&lt;/span&gt;
 &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0010&lt;/span&gt;
 &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0011&lt;/span&gt;
 &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0100&lt;/span&gt;
 &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0101&lt;/span&gt;
 &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0110&lt;/span&gt;
 &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0111&lt;/span&gt; &lt;span class="c1"&gt;// Octal system's digits 0-7 can represent up to three bits&lt;/span&gt;
 &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="c1"&gt;// This would be 10 in octal, requiring two digits&lt;/span&gt;
 &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;
 &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1010&lt;/span&gt;
 &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1011&lt;/span&gt;
 &lt;span class="nx"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1100&lt;/span&gt;
 &lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1101&lt;/span&gt;
 &lt;span class="nx"&gt;E&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1110&lt;/span&gt;
 &lt;span class="nx"&gt;F&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1111&lt;/span&gt; &lt;span class="c1"&gt;// While one hexadecimal digit can represent up to four bits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way we can just write &lt;code&gt;F0 0F&lt;/code&gt; when we mean &lt;code&gt;1111 0000 000 1111&lt;/code&gt;, for example.&lt;/p&gt;

&lt;p&gt;Finally, especially in the context of programming where we can mix'n'match different numeral systems together in the same source file, we often use prefixes like &lt;code&gt;0b&lt;/code&gt; for binary and &lt;code&gt;0x&lt;/code&gt; for hexadecimal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mb"&gt;0b10&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mh"&gt;0x2&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mb"&gt;0b1010&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mh"&gt;0xA&lt;/span&gt;
&lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mb"&gt;0b10_0000&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mh"&gt;0x20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>programming</category>
      <category>discuss</category>
      <category>learning</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Composition over Inheritance through example: ICE vs EV</title>
      <dc:creator>Mahi</dc:creator>
      <pubDate>Tue, 21 Jan 2025 13:57:31 +0000</pubDate>
      <link>https://dev.to/mahime/composition-over-inheritance-ice-vs-ev-24cj</link>
      <guid>https://dev.to/mahime/composition-over-inheritance-ice-vs-ev-24cj</guid>
      <description>&lt;p&gt;Recently, I wrote about &lt;a href="https://dev.to/mahime/why-i-dont-seal-my-classes-and-why-you-shouldnt-either-24n8"&gt;why I don't seal my classes&lt;/a&gt; and included an example of a &lt;code&gt;Car&lt;/code&gt; class that represented an internal combustion engine (ICE) vehicle—due to the designer not foreseeing future technologies. Years later someone needed an electric vehicle and had to inherit it from the ICE &lt;code&gt;Car&lt;/code&gt; to keep things backwards compatible and to avoid code duplication.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi5zp7cqqaev00faa2ef3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi5zp7cqqaev00faa2ef3.png" alt="Example misdesign: EV inherits Car/ICE" width="530" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This example made sense in the context of inheriting due to historical design flaws, but if we were to redesign the application from scratch then this obviously wouldn't be the ideal solution. But what would be?&lt;/p&gt;

&lt;h2&gt;
  
  
  The common base class approach
&lt;/h2&gt;

&lt;p&gt;The first idea most people think of is to separate the ICE and EV classes and have them inherit from a common base class:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8twpw942j5nt18f4axjp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8twpw942j5nt18f4axjp.png" alt="EV and ICE both inherit from a common  raw `Car` endraw  base class" width="492" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is already a &lt;em&gt;much&lt;/em&gt; better approach, and I would be happy to join such project. But there are flaws, especially when new technologies emerge (hydrogen, nuclear...).&lt;/p&gt;

&lt;p&gt;First of all, you are often faced with the issue of sub types needing &lt;em&gt;most&lt;/em&gt; of the common functionality, but not all of it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl9f1tj70m1z9lyi6cjma.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl9f1tj70m1z9lyi6cjma.png" alt="Every sub type has one unique feature implementation." width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this situation you mostly have bad choices available, the two most common ones being:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep the base class's implementation minimal and delegate the job to sub types. This often leads to numerous template and &lt;code&gt;abstract&lt;/code&gt; methods, with most sub types just duplicating the same implementation for them.&lt;/li&gt;
&lt;li&gt;Include the most common implementations into the base class, then have the exceptional sub types override this implementation. This often ends up breaking the Liskov substitution principle, and is smelly anyways.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As you can tell, neither of these approaches are ideal. It's still a clear improvement over the initial approach, but we can do better.&lt;/p&gt;

&lt;h2&gt;
  
  
  The composition approach
&lt;/h2&gt;

&lt;p&gt;My ideal approach is to use composition &lt;em&gt;together&lt;/em&gt; with polymorphism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; compose a &lt;code&gt;Car&lt;/code&gt; base class out of its smaller parts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;PowerTrain&lt;/span&gt; &lt;span class="nx"&gt;powerTrain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Motor, engine...&lt;/span&gt;
  &lt;span class="nx"&gt;EnergyStorage&lt;/span&gt; &lt;span class="nx"&gt;energyStorage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Gas tank, battery pack...&lt;/span&gt;
  &lt;span class="nx"&gt;EnergyAccessPoint&lt;/span&gt; &lt;span class="nx"&gt;eap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Charging port, refueling hatch...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Implement varying sub types of these smaller parts:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbviwq79qupbgv49ogxfi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbviwq79qupbgv49ogxfi.png" alt="ICE and ElectricMotor implement PowerTrain, GasTank and BatteryPack implement EnergyStorage" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Compose the smaller parts into new vehicles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;iceVehicle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ICE&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GasTank&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ElectricMotor&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BatteryPack&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Automate the creation process with &lt;a href="https://refactoring.guru/design-patterns/creational-patterns" rel="noopener noreferrer"&gt;creational patterns&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;iceVehicle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;iceVehicleFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;evFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How deep to go?
&lt;/h2&gt;

&lt;p&gt;A good question some might have is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why implement sub types of these power trains and energy storages when you could compose them out of smaller parts as well?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer is simple: &lt;strong&gt;compose as deep as your domain problem requires you to&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you're building a mechanic simulator, then yes, constructing the internal combustion engine out of even smaller parts is very much something you will need to implement.&lt;/li&gt;
&lt;li&gt;But if you're implementing an open-world video game where the vehicles are just a minor part of the gameplay and the hoods of the cars will never be popped open, then you probably would have been fine with the initial approach of inheriting &lt;code&gt;EV&lt;/code&gt; and &lt;code&gt;ICE&lt;/code&gt; directly from the &lt;code&gt;Car&lt;/code&gt; base class.&lt;/li&gt;
&lt;li&gt;And sometimes with simple applications you might not need the car sub types at all, as simply sub typing the car's &lt;em&gt;appearance&lt;/em&gt; might be enough:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EvSound&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Sprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ev.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;iceVehicle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IceSound&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Sprite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;icev.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where experience and domain knowledge come into play: you have to stop the composing &lt;em&gt;somewhere&lt;/em&gt; to avoid implementing atoms into your project, but you shouldn't stop too early to keep things modular and extendable. I can only provide you with the necessary tools to build great software, you're going to have to use them yourself. Don't be afraid to experiment and fail, that's how you learn.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>oop</category>
      <category>programming</category>
      <category>learning</category>
    </item>
    <item>
      <title>The circle–ellipse non-problem</title>
      <dc:creator>Mahi</dc:creator>
      <pubDate>Mon, 20 Jan 2025 11:12:50 +0000</pubDate>
      <link>https://dev.to/mahime/the-circle-ellipse-non-problem-4i6p</link>
      <guid>https://dev.to/mahime/the-circle-ellipse-non-problem-4i6p</guid>
      <description>&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Circle%E2%80%93ellipse_problem" rel="noopener noreferrer"&gt;circle–ellipse problem&lt;/a&gt; claims that OOP's inheritance is flawed due to the simple case of a circle not being able to inherit from an ellipse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ellipse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;stretchHorizontally&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;stretchVertically&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Circle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Ellipse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Oops, a circle doesn't support horizontal and vertical stretch!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nor an ellipse being able to inherit from a circle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Circle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ellipse&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Circle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Oops, an ellipse doesn't support a constant 'radius' field!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this is obviously hogwash.&lt;/p&gt;

&lt;h2&gt;
  
  
  The data-efficient solution: Separate the two shapes completely
&lt;/h2&gt;

&lt;p&gt;We can hopefully all agree that an ellipse is not a circle, but what if we decided that a circle wasn't an ellipse either? Instead we could separate the classes from each other, and at most have them implement a common &lt;code&gt;Round&lt;/code&gt; interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="n"&gt;Round&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;getWidth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;getHeight&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Circle&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="n"&gt;Round&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;getWidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;getHeight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ellipse&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="n"&gt;Round&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;getWidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;getHeight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works, and it works pretty well to be honest, but there is an ideological problem that I can already hear half the readers screaming: &lt;strong&gt;mathematically a circle is also an ellipse, OOP is broken!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The ideal world solution: A circle class doesn't exist
&lt;/h2&gt;

&lt;p&gt;Find a ball with a constant radius, like a soccer ball or a tennis ball. Now step on it. Congratulations, you just broke OOP by changing an object's type from a ball to an ellipsoid with nothing but the bottom of your foot!&lt;/p&gt;

&lt;p&gt;Like I said earlier, hogwash.&lt;/p&gt;

&lt;p&gt;A ball is not a class, a ball is an object. An object of type ellipsoid that happens to have the same length in all three dimensions.&lt;/p&gt;

&lt;p&gt;Now apply this logic to the 2D world and we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ellipse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;createCircle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Ellipse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;stretchWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;stretchHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tennisCircle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Ellipse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createCircle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Oh no, why would an user of my class stretch their tennis circle!&lt;/span&gt;
&lt;span class="n"&gt;tennisCircle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stretchWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Wait, why would I care? Maybe their game supports bouncy circles.&lt;/span&gt;
&lt;span class="c1"&gt;// If not, they probably shouldn't have called that particular method.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this solves the "problem": the issue was never in inheritance itself, but in the assumption that a circle is a sub type of an ellipse. The issue becomes obvious when you consider writing a new sub type of &lt;code&gt;Human&lt;/code&gt; for a specific &lt;code&gt;height,weight&lt;/code&gt; combination.&lt;/p&gt;

&lt;p&gt;The real confusion stems from the English word "&lt;em&gt;is&lt;/em&gt;": while a human &lt;em&gt;is&lt;/em&gt; an animal in an inheritance sense, any particular person &lt;em&gt;is&lt;/em&gt; a human in an instantiation sense.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reality check
&lt;/h2&gt;

&lt;p&gt;Now to be fair there is an unfortunate real world issue with the ideal world solution: data efficiency. Our computers have a finite amount of memory in them, and wasting data is typically non-ideal.&lt;/p&gt;

&lt;p&gt;If you're working with a &lt;em&gt;very&lt;/em&gt; limited amount of memory or a &lt;em&gt;massive&lt;/em&gt; number of circles, then you might want to minimize the number of fields in your circle class. &lt;strong&gt;This is nothing but you taking a conscious step away from an ideal world implementation to bend to our hardware limitations&lt;/strong&gt;. And this is exactly why I introduced the alternative, data-efficient approach as well.&lt;/p&gt;

&lt;p&gt;At the end of the day all paradigms are just that, paradigms. They're not some universal laws you must abide by at all cost, and a great developer understands when to take the non-ideal route.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>oop</category>
      <category>discuss</category>
      <category>learning</category>
    </item>
    <item>
      <title>Why I don't seal my classes—and why you shouldn't either</title>
      <dc:creator>Mahi</dc:creator>
      <pubDate>Mon, 20 Jan 2025 09:37:40 +0000</pubDate>
      <link>https://dev.to/mahime/why-i-dont-seal-my-classes-and-why-you-shouldnt-either-24n8</link>
      <guid>https://dev.to/mahime/why-i-dont-seal-my-classes-and-why-you-shouldnt-either-24n8</guid>
      <description>&lt;p&gt;Most programming languages nowadays support &lt;code&gt;sealed&lt;/code&gt; classes (sometimes &lt;code&gt;final&lt;/code&gt; classes), which prevent the class from being extended or subclassed. Some languages seal their classes by default, like Kotlin, while others require you to explicitly seal them with a modifier keyword, like C#.&lt;/p&gt;

&lt;p&gt;Now I don't just &lt;em&gt;prefer&lt;/em&gt; the C# way, but as a matter of fact &lt;strong&gt;I have never sealed a single class of mine&lt;/strong&gt;. And neither should you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is sealing, &lt;em&gt;really?&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Simply put, sealing is equivalent to claiming that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I know better than those who come after me. I know what others will need this class for in the future even after I've left the company. I also know all the possible use-cases and what external users and clients will ever need this class for.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now I don't know how good the lead developers in your company are, but I'm personally not willing to make claims that require me to see the future with absolute certainty—thus I always leave my classes unsealed. Remember that &lt;em&gt;not&lt;/em&gt; sealing your classes isn't an invitation for everyone to start inheriting from everything; those people would break something &lt;em&gt;anyways&lt;/em&gt; and there's nothing you can do to stop them. Meanwhile sealing your classes &lt;em&gt;is&lt;/em&gt; you deciding for every single other developer out there, and claiming that &lt;em&gt;not one&lt;/em&gt; will ever need to make an exception. Bold claim to make.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the upsides of sealing a class?
&lt;/h2&gt;

&lt;p&gt;Performance. A compiler can make certain optimizations based on the information that a class won't be extended. If you're working on performance critical code, then yes, sealing a class &lt;em&gt;can be&lt;/em&gt; a reasonable thing to do.&lt;/p&gt;

&lt;p&gt;That's it. Any other upsides one can think of are mere misunderstandings. Refer to the FAQ section below, which I will be updating to debunk these misunderstandings as they arise.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the downsides of sealing a class?
&lt;/h2&gt;

&lt;p&gt;If you made a mistake in your class, nobody else can fix it in theirs—instead they will have to wait for you to fix the mistake in your original, sealed class. While a noble approach in theory, the novelty quickly wears off in practice when the project already has a thousand issues on GitHub and the maintainer is on a vacation in Majorca.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy6jmjcp3vratxc6poe5o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy6jmjcp3vratxc6poe5o.jpg" alt="Sealed vs unsealed class representation: blocking inheritance requires EV to duplicate all of Car's code" width="381" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, if someone needs a small variation of your class that you failed to predict 10 years ago, they're out of luck. Imagine having to rewrite the entire &lt;code&gt;Car&lt;/code&gt; class from scratch because the internal combustion engine (ICE) people sealed their classes and now you can't extend your electric vehicle from them. Or having to copy&amp;amp;paste the whole flying and rotor logic into a drone because people in 1990s didn't think that helicopters could ever get small enough to not carry personnel. &lt;em&gt;"Sorry, this class is sealed to only carry people."&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; Good design doesn't require inheritance, a drone can be composed of smaller parts of a helicopter and both an EV and an ICE can be composed from common parts!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ah yes, favor composition over inheritance.&lt;/p&gt;

&lt;p&gt;Of course the full quote from &lt;em&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/em&gt; (which popularized the whole composition over inheritance principle) is more akin to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ideally all reuse can be achieved by assembling existing components, but in practice inheritance is often needed to make new ones. Therefore inheritance and object composition typically work hand-in-hand.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that's a direct quote from &lt;a href="https://en.wikipedia.org/wiki/Composition_over_inheritance" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;, but I'm the one who wrote that Wikipedia entry after reading the original book, so I'll let it pass this time.&lt;/p&gt;

&lt;p&gt;What's important to note here is that already in 1994 when the book was originally published did they acknowledge that &lt;em&gt;ideally&lt;/em&gt; everything is composed but &lt;em&gt;in practice&lt;/em&gt; inheritance is needed. Why? Because nobody is perfect, nobody can see the future, and nobody can predict all the possible use-cases. Miss one use-case in your sealed class's design and your clients are going to hate you in 10 years. This is when inheritance comes into play, and this is why you don't seal your classes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; How to ensure nobody breaks my classes?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Don't give them push/merge permissions to your project. If they break the code on &lt;em&gt;their&lt;/em&gt; end, that's not your problem. If I incorrectly extend Angular's components or Qt's Widgets or write an invalid extension for Firefox, did I just break their code or mine?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; But the &lt;a href="https://en.wikipedia.org/wiki/Fragile_base_class" rel="noopener noreferrer"&gt;fragile base class problem&lt;/a&gt;!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A rare niche case where changing a base class's implementation (cross-calls between its methods) after it was extended would break the extending subclass. How about let's not completely prohibit one of the most powerful ways of extending code after a new unforeseen use-case arises on the off-chance that we ourselves change the way our class cross-calls its own methods, no?&lt;/p&gt;

&lt;p&gt;If you need to make such fragile changes commonly, then you're doing something horribly wrong. And if you only need them once or twice over a 10 year lifespan—like a normal developer does—then you can introduce the change as a major breaking change and go as far as changing the method names while at it. As a matter of fact, over my 20 years of experience I have only needed to introduce a fragile base class change exactly &lt;em&gt;once&lt;/em&gt;. And that was because the initial design had been wrong.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>discuss</category>
      <category>oop</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
