site

personal website, served at mordaunt.dev/site
Log | Files | Refs

index.html (29912B)


      1 <!DOCTYPE html>
      2 <html lang="en">
      3 
      4 <head>
      5   <title>
      6   What is an Interface · Jack Mordaunt
      7 </title>
      8   <meta charset="utf-8">
      9 <meta name="viewport" content="width=device-width, initial-scale=1.0">
     10 <meta name="color-scheme" content="light dark">
     11 
     12 
     13 
     14 
     15 <meta name="author" content="Jack Mordaunt">
     16 <meta name="description" content="Behavioral Polymorphism: The foundation of OOP.">
     17 <meta name="keywords" content="blog,developer,personal,software,robust,performance,sovereign">
     18 
     19 
     20 
     21   <meta name="twitter:card" content="summary">
     22   <meta name="twitter:title" content="What is an Interface">
     23   <meta name="twitter:description" content="Behavioral Polymorphism: The foundation of OOP.">
     24 
     25 <meta property="og:url" content="http://jackmordaunt.com/posts/what-is-an-interface/">
     26   <meta property="og:site_name" content="Jack Mordaunt">
     27   <meta property="og:title" content="What is an Interface">
     28   <meta property="og:description" content="Behavioral Polymorphism: The foundation of OOP.">
     29   <meta property="og:locale" content="en">
     30   <meta property="og:type" content="article">
     31     <meta property="article:section" content="posts">
     32     <meta property="article:published_time" content="2025-08-01T06:26:18-03:00">
     33     <meta property="article:modified_time" content="2025-08-01T06:26:18-03:00">
     34     <meta property="article:tag" content="OOP">
     35     <meta property="article:tag" content="Go">
     36     <meta property="article:tag" content="Odin">
     37     <meta property="article:tag" content="Interface">
     38 
     39 
     40 
     41 
     42 <link rel="canonical" href="http://jackmordaunt.com/posts/what-is-an-interface/">
     43 
     44 
     45 <link rel="preload" href="/fonts/fa-brands-400.woff2" as="font" type="font/woff2" crossorigin>
     46 <link rel="preload" href="/fonts/fa-regular-400.woff2" as="font" type="font/woff2" crossorigin>
     47 <link rel="preload" href="/fonts/fa-solid-900.woff2" as="font" type="font/woff2" crossorigin>
     48 
     49 
     50   
     51   
     52   <link rel="stylesheet" href="/css/coder.min.6445a802b9389c9660e1b07b724dcf5718b1065ed2d71b4eeaf981cc7cc5fc46.css" integrity="sha256-ZEWoArk4nJZg4bB7ck3PVxixBl7S1xtO6vmBzHzF/EY=" crossorigin="anonymous" media="screen" />
     53 
     54 
     55 
     56 
     57 
     58 
     59   
     60     
     61     
     62     <link rel="stylesheet" href="/css/coder-dark.min.a00e6364bacbc8266ad1cc81230774a1397198f8cfb7bcba29b7d6fcb54ce57f.css" integrity="sha256-oA5jZLrLyCZq0cyBIwd0oTlxmPjPt7y6KbfW/LVM5X8=" crossorigin="anonymous" media="screen" />
     63   
     64 
     65 
     66 
     67  
     68   
     69     
     70     <link rel="stylesheet" href="/css/custom.min.931a9d02d6f7655cd0cd50317fac1204e00c54ffd0232085acc957b2db5e1283.css" integrity="sha256-kxqdAtb3ZVzQzVAxf6wSBOAMVP/QIyCFrMlXstteEoM=" crossorigin="anonymous" media="screen" />
     71   
     72 
     73 
     74 
     75 
     76 
     77 <link rel="icon" type="image/svg+xml" href="/images/self-tiny-white.svg" sizes="any">
     78 <link rel="icon" type="image/png" href="/images/self-tiny-white.png" sizes="32x32">
     79 <link rel="icon" type="image/png" href="/images/self-tiny-white.png" sizes="16x16">
     80 
     81 <link rel="apple-touch-icon" href="/images/apple-touch-icon.png">
     82 <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png">
     83 
     84 <link rel="manifest" href="/site.webmanifest">
     85 <link rel="mask-icon" href="/images/safari-pinned-tab.svg" color="#5bbad5">
     86 
     87 
     88 
     89 
     90 
     91 
     92 
     93 <script defer data-domain="jackmordaunt.com" src="https://plausible.io/js/script.js"></script>
     94 
     95 
     96 
     97 
     98 </head>
     99 
    100 
    101 
    102 
    103 
    104 
    105 <body class="preload-transitions colorscheme-auto">
    106   
    107 <div class="float-container">
    108     <a id="dark-mode-toggle" class="colorscheme-toggle">
    109         <i class="fa-solid fa-adjust fa-fw" aria-hidden="true"></i>
    110     </a>
    111 </div>
    112 
    113 
    114   <main class="wrapper">
    115     <nav class="navigation">
    116   <section class="container">
    117     
    118     <a class="navigation-title" href="http://jackmordaunt.com/">
    119       Jack Mordaunt
    120     </a>
    121     
    122     
    123       <input type="checkbox" id="menu-toggle" />
    124       <label class="menu-button float-right" for="menu-toggle">
    125         <i class="fa-solid fa-bars fa-fw" aria-hidden="true"></i>
    126       </label>
    127       <ul class="navigation-list">
    128         
    129           
    130             <li class="navigation-item">
    131               <a class="navigation-link " href="/posts/">Blog</a>
    132             </li>
    133           
    134             <li class="navigation-item">
    135               <a class="navigation-link " href="/about/">About</a>
    136             </li>
    137           
    138             <li class="navigation-item">
    139               <a class="navigation-link " href="/projects/">Projects</a>
    140             </li>
    141           
    142             <li class="navigation-item">
    143               <a class="navigation-link " href="/contact/">Contact</a>
    144             </li>
    145           
    146             <li class="navigation-item">
    147               <a class="navigation-link " href="/pay-with-bitcoin/">Pay</a>
    148             </li>
    149           
    150         
    151         
    152       </ul>
    153     
    154   </section>
    155 </nav>
    156 
    157 
    158     <div class="content">
    159       
    160   <section class="container post">
    161     <article>
    162       <header>
    163         <div class="post-title">
    164           <h1 class="title">
    165             <a class="title-link" href="http://jackmordaunt.com/posts/what-is-an-interface/">
    166               What is an Interface
    167             </a>
    168           </h1>
    169         </div>
    170         <div class="post-meta">
    171           <div class="date">
    172             <span class="posted-on">
    173               <i class="fa-solid fa-calendar" aria-hidden="true"></i>
    174               <time datetime="2025-08-01T06:26:18-03:00">
    175                 August 1, 2025
    176               </time>
    177             </span>
    178             <span class="reading-time">
    179               <i class="fa-solid fa-clock" aria-hidden="true"></i>
    180               6-minute read
    181             </span>
    182           </div>
    183           
    184           
    185           <div class="tags">
    186   <i class="fa-solid fa-tag" aria-hidden="true"></i>
    187     <span class="tag">
    188       <a href="/tags/oop/">OOP</a>
    189     </span>
    190       <span class="separator">•</span>
    191     <span class="tag">
    192       <a href="/tags/go/">Go</a>
    193     </span>
    194       <span class="separator">•</span>
    195     <span class="tag">
    196       <a href="/tags/odin/">Odin</a>
    197     </span>
    198       <span class="separator">•</span>
    199     <span class="tag">
    200       <a href="/tags/interface/">Interface</a>
    201     </span></div>
    202 
    203         </div>
    204       </header>
    205 
    206       <div class="post-content">
    207         
    208         <p><strong>Behavioral Polymorphism: The foundation of OOP.</strong></p>
    209 <p>The <strong>interface</strong> is the foundation of OOP (Object Oriented Programming).</p>
    210 <p>It provides <em>behavioral polymorphism</em>: constraining a type by its behaviours -
    211 or more secifically, its method-set.</p>
    212 <blockquote>
    213 <p>A &ldquo;method&rdquo; (as termed in OOP langauges) is nothing more than a procedure who&rsquo;s
    214 first argument is a pointer to the object it is associated with. There is
    215 nothing special about a method.</p></blockquote>
    216 <p><strong>Definitions</strong></p>
    217 <ul>
    218 <li><strong>Poly</strong>: many</li>
    219 <li><strong>Mono</strong>: singular</li>
    220 <li><strong>Morphism</strong>: shape</li>
    221 <li><strong>Polymorphism</strong>: having many shapes</li>
    222 <li><strong>Monomorphism</strong>: having one shape</li>
    223 </ul>
    224 <p>Polymorphic refers to the ability to represent many shapes.</p>
    225 <p><strong>Anology: Power Sockets</strong></p>
    226 <p>You might have ten electrical appliances all completely different.
    227 Toaster, microwave, blender.
    228 The way they use the electricity are all different, but the power plug is the same.
    229 The power socket provides a common interface that allows polymorphism with respect to the appliances.
    230 As long as an appliance has a the correct plug, the power socket will accept it.
    231 Thus the power socket is an interface that enables behavioral polymorphism.</p>
    232 <p>Polymorphism in programing works the same way.</p>
    233 <blockquote>
    234 <p>In dynamically-typed programming every value is polymorphic, and only the <em>use</em> of the value will reveal whether the particular morphism is valid.
    235 In statically-typed programming every value is monomorphic, and special types must be used to allow for polymorphism.</p></blockquote>
    236 <p><strong>What is a shape anyway?</strong></p>
    237 <p>In programming a shape is some definable characteristic about a value.</p>
    238 <ul>
    239 <li>At a low level: how are the fields represented in memory</li>
    240 <li>At a high level: is it iterable, is it indexable, is it a reference, etc</li>
    241 </ul>
    242 <p>We abstract the low level up to the high level.</p>
    243 <p>OOP languages often build in language-level native support for interfaces since
    244 this kind of polymorphism is foundational to the OOP paradigm. In low level
    245 languages like C you will typically achieve polymorphism through data layout:
    246 using flexible structures and memory indirection.</p>
    247 <p>Interfaces allow for polymorphism in statically-typed languages.
    248 That is, they don&rsquo;t require generics in the type-system to implement.</p>
    249 <p>It is no coincidence that Java and Go started out statically-typed using interfaces.
    250 Lacking parametric polymorphism, those languages often awkwardly relied on behavioral polymorphism.</p>
    251 <h2 id="the-fat-pointer">
    252   The Fat Pointer
    253   <a class="heading-link" href="#the-fat-pointer">
    254     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    255     <span class="sr-only">Link to heading</span>
    256   </a>
    257 </h2>
    258 <p>This section applies to <em>runtime</em> interfaces, otherwise known as <em>dynamic dispatch</em>.</p>
    259 <p>At the low level, an interface is nothing more than a <strong>fat pointer</strong>: a structure
    260 containing a pair of pointers - one that points to the data, and the other that
    261 points to a function that operates on the data.</p>
    262 <p>This is all you need.</p>
    263 <p><strong>Odin Example: Stream</strong></p>
    264 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-odin" data-lang="odin"><span style="display:flex;"><span>Stream_Proc<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">::</span><span style="color:#6e7681"> </span><span style="color:#d2a8ff;font-weight:bold">#type</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">proc</span>(stream_data<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">rawptr</span>,<span style="color:#6e7681"> </span>mode<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>Stream_Mode,<span style="color:#6e7681"> </span>p<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>[]<span style="color:#ff7b72">byte</span>,<span style="color:#6e7681"> </span>offset<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">i64</span>,<span style="color:#6e7681"> </span>whence<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>Seek_From)<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">-&gt;</span><span style="color:#6e7681"> </span>(n<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">i64</span>,<span style="color:#6e7681"> </span>err<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>Error)<span style="color:#6e7681">
    265 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    266 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>Stream<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">::</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">struct</span><span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    267 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span>procedure<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>Stream_Proc,<span style="color:#6e7681">
    268 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span>data<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681">      </span><span style="color:#ff7b72">rawptr</span>,<span style="color:#6e7681">
    269 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>}<span style="color:#6e7681">
    270 </span></span></span></code></pre></div><p>This struct contains a pointer to a procedure and a pointer to the data.
    271 It can be used to represent any kind of streaming operation: reading, writing, flushing, closing, etc, on any type.</p>
    272 <p>Each specialized type (file, buffer, http body) simply needs to map itself to this shape and it can integrate with streaming logic.</p>
    273 <p><strong>Converting a Buffer to a Stream</strong></p>
    274 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-odin" data-lang="odin"><span style="display:flex;"><span>buffer_to_stream<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">::</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">proc</span>(b<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">^</span>Buffer)<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">-&gt;</span><span style="color:#6e7681"> </span>(s<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>io.Stream)<span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    275 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span>s.data<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span>b<span style="color:#6e7681">
    276 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span>s.procedure<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span>_buffer_proc<span style="color:#6e7681">
    277 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span><span style="color:#ff7b72">return</span><span style="color:#6e7681">
    278 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>}<span style="color:#6e7681">
    279 </span></span></span></code></pre></div><p>It simply builds the stream struct using a pointer to the buffer sets the correct procedure.</p>
    280 <p>To achieve behavioral polymorphism all you need is a common
    281 representation (the fat pointer) that all specialized types can conform to.</p>
    282 <p><strong>Usage Example: io.Reader</strong></p>
    283 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-odin" data-lang="odin"><span style="display:flex;"><span><span style="color:#ff7b72">package</span><span style="color:#6e7681"> </span>main<span style="color:#6e7681">
    284 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    285 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span><span style="color:#ff7b72">import</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#34;core:bytes&#34;</span><span style="color:#6e7681">
    286 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span><span style="color:#ff7b72">import</span><span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#34;core:io&#34;</span><span style="color:#6e7681">
    287 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span><span style="color:#ff7b72">import</span><span style="color:#6e7681"> </span>os<span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#34;core:os/os2&#34;</span><span style="color:#6e7681">
    288 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    289 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>main<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">::</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">proc</span>()<span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    290 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span><span style="color:#8b949e;font-style:italic">// Assign both the file and buffer reader to this to show they are the same shape.
    291 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span><span style="color:#6e7681">	</span>reader<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>io.Reader<span style="color:#6e7681">
    292 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    293 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span><span style="color:#8b949e;font-style:italic">// Scratch is just a buffer to read into.
    294 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span><span style="color:#6e7681">	</span>scratch<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">:=</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">make</span>([<span style="color:#ff7b72">dynamic</span>]<span style="color:#ff7b72">byte</span>,<span style="color:#6e7681"> </span>1024<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">*</span><span style="color:#6e7681"> </span>1024)<span style="color:#6e7681">
    295 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    296 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span><span style="color:#8b949e;font-style:italic">// Open a file and make a reader for it.
    297 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span><span style="color:#6e7681">	</span>file,<span style="color:#6e7681"> </span>_<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">:=</span><span style="color:#6e7681"> </span>os.open(<span style="color:#a5d6ff">&#34;file&#34;</span>)<span style="color:#6e7681">
    298 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span>reader<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span>os.to_reader(file)<span style="color:#6e7681">
    299 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    300 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span><span style="color:#8b949e;font-style:italic">// This call is operating on the file.
    301 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span><span style="color:#6e7681">	</span>io.read_full(reader,<span style="color:#6e7681"> </span>scratch[<span style="color:#ff7b72;font-weight:bold">:</span>])<span style="color:#6e7681">
    302 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    303 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span><span style="color:#8b949e;font-style:italic">// Allocate a byte buffer and make a reader for it.
    304 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span><span style="color:#6e7681">	</span>buf<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>bytes.Buffer<span style="color:#6e7681">
    305 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span>bytes.buffer_init(<span style="color:#ff7b72;font-weight:bold">&amp;</span>buf,<span style="color:#6e7681"> </span><span style="color:#ff7b72">make</span>([<span style="color:#ff7b72">dynamic</span>]<span style="color:#ff7b72">byte</span>,<span style="color:#6e7681"> </span>1024<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">*</span><span style="color:#6e7681"> </span>1024)[<span style="color:#ff7b72;font-weight:bold">:</span>])<span style="color:#6e7681">
    306 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span>reader<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span>bytes.buffer_to_stream(<span style="color:#ff7b72;font-weight:bold">&amp;</span>buf)<span style="color:#6e7681">
    307 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    308 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">	</span><span style="color:#8b949e;font-style:italic">// This call is operating on the buffer.
    309 </span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic"></span><span style="color:#6e7681">	</span>io.read_full(reader,<span style="color:#6e7681"> </span>scratch[<span style="color:#ff7b72;font-weight:bold">:</span>])<span style="color:#6e7681">
    310 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>}<span style="color:#6e7681">
    311 </span></span></span></code></pre></div><p>In this example, the <code>io.Reader</code> is the interface.
    312 The <code>bytes.Buffer</code> and the <code>os.File</code> are the specialized types can map to it.
    313 <code>io.read_full</code> can therefore operate on any type that can map to an <code>io.Reader</code>.</p>
    314 <p>Behavioral polymorphism is achieved by matching shapes. No runtime or type system
    315 support needed.</p>
    316 <h2 id="the-vtable">
    317   The VTable
    318   <a class="heading-link" href="#the-vtable">
    319     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    320     <span class="sr-only">Link to heading</span>
    321   </a>
    322 </h2>
    323 <p><strong>Virtual Table</strong></p>
    324 <p>The Odin core prefers to (but doesn&rsquo;t require) to use a VTable-of-one. A single
    325 procedure that can handle any possible operation of the interface.</p>
    326 <p>This keeps the shape a simple fat-pointer, making it easier to construct and
    327 more compact in memory.</p>
    328 <p>The traditional way (e.g., C++) assigns each method its own entry in the VTable.
    329 This means the pointer to the procedure becomes a pointer to a table of procedures.</p>
    330 <p>Each entry into the virtual table represents a single method.</p>
    331 <p><strong>Example: Multi-Method VTable</strong></p>
    332 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-odin" data-lang="odin"><span style="display:flex;"><span>FileInterface<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">::</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">struct</span><span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    333 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span>vtable<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>FileVTable,<span style="color:#6e7681">
    334 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span>data<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">rawptr</span>,<span style="color:#6e7681">
    335 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>}<span style="color:#6e7681">
    336 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
    337 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>FileVTable<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">::</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">struct</span><span style="color:#6e7681"> </span>{<span style="color:#6e7681">
    338 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span>read<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">proc</span>(data<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">rawptr</span>,<span style="color:#6e7681"> </span>p<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">byte</span>[])<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">-&gt;</span><span style="color:#6e7681"> </span>(n<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">int</span>,<span style="color:#6e7681"> </span>err<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>Error),<span style="color:#6e7681">
    339 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span>write<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">proc</span>(data<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">rawptr</span>,<span style="color:#6e7681"> </span>p<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">byte</span>[])<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">-&gt;</span><span style="color:#6e7681"> </span>(n<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">int</span>,<span style="color:#6e7681"> </span>err<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span>Error),<span style="color:#6e7681">
    340 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681">  </span>close<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">proc</span>(data<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">rawptr</span>)<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">-&gt;</span><span style="color:#6e7681"> </span>Error,<span style="color:#6e7681">
    341 </span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span>}<span style="color:#6e7681">
    342 </span></span></span></code></pre></div><p>As you can see, each additional method increases the memory required.</p>
    343 <p>There is no <strong>logical</strong> difference between the two representations, only structural.</p>
    344 <h2 id="windows-com">
    345   Windows COM
    346   <a class="heading-link" href="#windows-com">
    347     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    348     <span class="sr-only">Link to heading</span>
    349   </a>
    350 </h2>
    351 <p>To see how far you can take behavioral polymorphism, look no further than Windows COM.</p>
    352 <p>COM is an API and ABI implemented entirely around VTables — to the exclusion of all else.</p>
    353 <p>You can call and implement a COM object in <em>any</em> langauge, as long as the VTable
    354 representation and behaviour of the methods are correct.</p>
    355 <p>The point is not to teach COM, but to illustrate that interfaces are just VTables.
    356 Behavioral polymorphism is a simple low-level idea that is abstracted into OOP
    357 languages as a first class language feature.</p>
    358 <p>Windows COM also shows how flexible the humble VTable can be — it allows a
    359 polyglot object system. Fascinating, but probably not something to aspire to.</p>
    360 <h2 id="the-cost">
    361   The Cost
    362   <a class="heading-link" href="#the-cost">
    363     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    364     <span class="sr-only">Link to heading</span>
    365   </a>
    366 </h2>
    367 <p>Interfaces are simple structures, but they are not free.</p>
    368 <ul>
    369 <li><strong>Size</strong>: at a minimum, two pointers.</li>
    370 <li><strong>Growth</strong>: VTable size grows with number of methods.</li>
    371 <li><strong>Indirection</strong>: Runtime method calls are indirect.</li>
    372 </ul>
    373 <p>In large dynamic arrays, interface overhead can add up:</p>
    374 <ul>
    375 <li><strong>Memory cost</strong></li>
    376 <li><strong>Cache pressure</strong> due to pointer indirection</li>
    377 <li><strong>Fragmented memory</strong> for the actual data</li>
    378 </ul>
    379 <p>With a more sophisticated type system, interfaces can be monomorphised at
    380 compile-time (i.e., static dispatch).</p>
    381 <p>This eliminates runtime cost but increases compile-time complexity.</p>
    382 <h2 id="conclusion">
    383   Conclusion
    384   <a class="heading-link" href="#conclusion">
    385     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    386     <span class="sr-only">Link to heading</span>
    387   </a>
    388 </h2>
    389 <p>Interfaces allow behavioral polymorpshim.</p>
    390 <p>The classic runtime interface is implemented as a simple fat-pointer shape.</p>
    391 <p>Concrete types only need to satisfy the shape of the interface and they can be used anywhere
    392 that interface is used.</p>
    393 <p>Interfaces are not scary, and not hard to implement at the low level. They are also not a
    394 substitute for parametric polymorphism as I&rsquo;m sure many Go programmers are well aware.</p>
    395 
    396       </div>
    397 
    398 
    399       <footer>
    400         
    401 
    402 
    403         
    404         
    405         
    406         
    407         
    408         
    409         
    410       </footer>
    411     </article>
    412 
    413     
    414   </section>
    415 
    416     </div>
    417 
    418     <footer class="footer">
    419   <section class="container">
    420     ©
    421     
    422     2025
    423      Jack Mordaunt 
    424     ·
    425     
    426     Powered by <a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a> & <a href="https://github.com/luizdepra/hugo-coder/" target="_blank" rel="noopener">Coder</a>.
    427     
    428   </section>
    429 </footer>
    430 
    431   </main>
    432 
    433   
    434 
    435   
    436   
    437   <script src="/js/coder.min.6ae284be93d2d19dad1f02b0039508d9aab3180a12a06dcc71b0b0ef7825a317.js" integrity="sha256-auKEvpPS0Z2tHwKwA5UI2aqzGAoSoG3McbCw73gloxc="></script>
    438   
    439 
    440   
    441 
    442   
    443 
    444 
    445   
    446 
    447   
    448 
    449   
    450 
    451   
    452 
    453   
    454 
    455   
    456 
    457   
    458 
    459   
    460 
    461   
    462 
    463   
    464 
    465   
    466 
    467   
    468 
    469   
    470 
    471   
    472 
    473   
    474 
    475   
    476 
    477   
    478 </body>
    479 </html>