{"id":2502,"date":"2021-01-28T19:01:00","date_gmt":"2021-01-28T18:01:00","guid":{"rendered":"https:\/\/gdksoftware.com\/knowledgebase\/solid-principles-in-delphi-2-the-open-closed-principle"},"modified":"2021-03-25T11:01:25","modified_gmt":"2021-03-25T10:01:25","slug":"solid-principles-in-delphi-2-the-open-closed-principle","status":"publish","type":"knowledge","link":"https:\/\/gdksoftware.com\/nl\/kennisbank\/solid-principles-in-delphi-2-the-open-closed-principle","title":{"rendered":"SOLID Principes in Delphi [2] &#8211; Het Open\/Closed principe"},"content":{"rendered":"<p>Het tweede principe van S<strong>O<\/strong>LID is het Open\/Closed principe: &#8220;Klassen en andere entiteiten moeten open zijn voor uitbreiding, maar gesloten voor wijziging&#8221;. Dit artikel gaat over hoe je in Delphi een klasse gesloten houdt voor modificatie, maar open voor uitbreiding.<\/p>\n<p>Laat ik \u00e9\u00e9n onderdeel benadrukken; dit doel bereiken via overerving of het overriden van classes is naar mijn mening een slecht idee. Als je hier meer over wilt lezen, kijk dan eens wat Bertrand Mayer en Robert C. Martin over dit onderwerp te zeggen hebben.<\/p>\n<p>Ok, laten we het volgende voorbeeld nemen:<\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">type<\/span>\r\n  TShip <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span>\r\n    <span style=\"color: #888888;\">\/\/ This is the actual ship<\/span>\r\n  <span style=\"color: #008800; font-weight: bold;\">end<\/span><span style=\"color: #333333;\">;<\/span>\r\n\r\n  TPartList <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span>\r\n    <span style=\"color: #888888;\">\/\/ This class holds all the needed parts for building a ship<\/span>\r\n  <span style=\"color: #008800; font-weight: bold;\">end<\/span><span style=\"color: #333333;\">;<\/span>\r\n\r\n  TShipLayout <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span>\r\n    <span style=\"color: #888888;\">\/\/ This class provides the blueprint of the ship to build<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">function<\/span> <span style=\"color: #0066bb; font-weight: bold;\">GetBlueprint<\/span><span style=\"color: #333333;\">:<\/span> TList<span style=\"color: #333333;\">&lt;<\/span>TPoint<span style=\"color: #333333;\">&gt;;<\/span> <span style=\"color: #888888;\">\/\/ just as an example<\/span>\r\n  <span style=\"color: #008800; font-weight: bold;\">end<\/span><span style=\"color: #333333;\">;<\/span>\r\n\r\n  <span style=\"color: #888888;\">\/\/ This is the factory class to build a ship<\/span>\r\n  TShipBuilder <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span>\r\n  <span style=\"color: #003388; font-weight: bold;\">private<\/span>\r\n    FParts<span style=\"color: #333333;\">:<\/span> TPartList<span style=\"color: #333333;\">;<\/span>\r\n    FShipLayout<span style=\"color: #333333;\">:<\/span> TShipLayout<span style=\"color: #333333;\">;<\/span>\r\n  <span style=\"color: #003388; font-weight: bold;\">public<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">procedure<\/span> <span style=\"color: #0066bb; font-weight: bold;\">LoadParts<\/span>(APartList<span style=\"color: #333333;\">:<\/span> TPartList)<span style=\"color: #333333;\">;<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">procedure<\/span> <span style=\"color: #0066bb; font-weight: bold;\">LoadShipLayout<\/span>(ALayout<span style=\"color: #333333;\">:<\/span> TShipLayout)<span style=\"color: #333333;\">;<\/span>\r\n\r\n    <span style=\"color: #008800; font-weight: bold;\">function<\/span> <span style=\"color: #0066bb; font-weight: bold;\">BuildShip<\/span><span style=\"color: #333333;\">:<\/span> TShip<span style=\"color: #333333;\">;<\/span>\r\n  <span style=\"color: #008800; font-weight: bold;\">end<\/span><span style=\"color: #333333;\">;<\/span>\r\n<\/pre>\n<\/div>\n<p>Zoals je kunt zien, zijn dit eenvoudige klassen, zonder interfaces en zonder de mogelijkheid ze gemakkelijk uit te breiden. De ShipBuilder klasse is echter al (gedeeltelijk) gesloten voor modificatie; de interne werking is gescheiden van de buitenwereld doordat de lokale variabelen private zijn gemaakt. In Delphi heb je echter nog steeds toegang tot deze variabelen als je deze klasse vanuit hetzelfde bestand benadert. Een eenvoudige verbetering is daarom om van de private een <strong>strict<\/strong> private te maken.<\/p>\n<p>De interne werking van deze klasse zelf is echter nog steeds open voor wijzigingen. Je kunt gemakkelijk de BuildShip functie gebruiker voordat je zelfs maar de ShipParts en de Shipslayout gezet hebt.<\/p>\n<p>Maar hoe zorgen we ervoor dat deze class open is voor uitbreiding, maar gesloten blijft voor wijziging?<\/p>\n<p>Het antwoord? Interfaces!<\/p>\n<p>Waarom interfaces? Dit heeft te maken met een ander principe: programmeer tegen interfaces en niet tegen implementaties. Het voorbeeld hierboven is de implementatie van de klasse TShipBuilder. Zodra je met deze implementatie gaat werken, zit je automatisch ook &#8216;vast&#8217; aan de TPartList en TShipLayout implementaties. Laten we eens kijken hoe we dit kunnen verbeteren. De eerste stap is om verschillende interfaces te cre\u00ebren en de TShipBuilder klasse aan te passen om die nieuwe interfaces te implementeren. De tweede stap is om dependency injection te gebruiken om deze klasse open te stellen voor uitbreiding, maar te sluiten voor wijziging. Als je dat doet, eindig je met iets als dit:<\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">type<\/span>\r\n  TShip <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span>\r\n    <span style=\"color: #888888;\">\/\/ This is the actual ship class<\/span>\r\n  <span style=\"color: #008800; font-weight: bold;\">end<\/span><span style=\"color: #333333;\">;<\/span>\r\n\r\n  IPartList <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">interface<\/span>\r\n    <span style=\"color: #888888;\">\/\/ Necessary info to provide the parts<\/span>\r\n  <span style=\"color: #008800; font-weight: bold;\">end<\/span><span style=\"color: #333333;\">;<\/span>\r\n\r\n  TPartList <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span>(TInterfacedObject<span style=\"color: #333333;\">,<\/span> IPartList)\r\n    <span style=\"color: #888888;\">\/\/ This class holds all the needed parts for building a ship<\/span>\r\n  <span style=\"color: #008800; font-weight: bold;\">end<\/span><span style=\"color: #333333;\">;<\/span>\r\n\r\n  IShipLayout <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">interface<\/span>\r\n    <span style=\"color: #888888;\">\/\/ Necessary info to provide the blueprint<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">function<\/span> <span style=\"color: #0066bb; font-weight: bold;\">GetBlueprint<\/span><span style=\"color: #333333;\">:<\/span> TList<span style=\"color: #333333;\">&lt;<\/span>TPoint<span style=\"color: #333333;\">&gt;;<\/span>\r\n  <span style=\"color: #008800; font-weight: bold;\">end<\/span><span style=\"color: #333333;\">;<\/span>\r\n\r\n  TShipLayout <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span>(TInterfacedObject<span style=\"color: #333333;\">,<\/span> IShipLayout)\r\n    <span style=\"color: #888888;\">\/\/ This class implements the blueprint function of the ship to build<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">function<\/span> <span style=\"color: #0066bb; font-weight: bold;\">GetBlueprint<\/span><span style=\"color: #333333;\">:<\/span> TList<span style=\"color: #333333;\">&lt;<\/span>TPoint<span style=\"color: #333333;\">&gt;;<\/span>\r\n  <span style=\"color: #008800; font-weight: bold;\">end<\/span><span style=\"color: #333333;\">;<\/span>\r\n\r\n  TShipBuilder <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span>\r\n  strict <span style=\"color: #003388; font-weight: bold;\">private<\/span>\r\n    FParts<span style=\"color: #333333;\">:<\/span> TPartList<span style=\"color: #333333;\">;<\/span>\r\n    FShipLayout<span style=\"color: #333333;\">:<\/span> TShipLayout<span style=\"color: #333333;\">;<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">procedure<\/span> <span style=\"color: #0066bb; font-weight: bold;\">LoadParts<\/span><span style=\"color: #333333;\">;<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">procedure<\/span> <span style=\"color: #0066bb; font-weight: bold;\">LoadShipLayout<\/span><span style=\"color: #333333;\">;<\/span>\r\n  <span style=\"color: #003388; font-weight: bold;\">public<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">constructor<\/span> <span style=\"color: #0066bb; font-weight: bold;\">Create<\/span>(APartList<span style=\"color: #333333;\">:<\/span> IPartList<span style=\"color: #333333;\">;<\/span> ALayout<span style=\"color: #333333;\">:<\/span> IShipLayout)<span style=\"color: #333333;\">;<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">function<\/span> <span style=\"color: #0066bb; font-weight: bold;\">BuildShip<\/span><span style=\"color: #333333;\">:<\/span> TShip<span style=\"color: #333333;\">;<\/span>\r\n  <span style=\"color: #008800; font-weight: bold;\">end<\/span><span style=\"color: #333333;\">;<\/span>\r\n<\/pre>\n<\/div>\n<p>Dus, wat hebben we nu precies gedaan? Zoals je kan zien, hebben we nu een TShipBuilder class die de twee interfaces vereist via een constructor. Zowel de LoadParts als de LoadShipLayout procedures worden strict private gemaakt, wat er voor zorgt dat de klasse gesloten is voor wijziging, zodat we deze procedures enkel gebruiken binnen bijvoorbeeld de BuildShip functie.<\/p>\n<p>Bovendien staat onze klasse open voor uitbreiding. Het is mogelijk om deze ShipLayout functionaliteit uit te breiden door bijvoorbeeld gewoon een andere implementatie van de IShipLayout interface te maken, zolang we de GetBlueprint functie maar implementeren. We moeten er alleen voor zorgen dat we een klasse met de ge\u00efmplementeerde IShipLayout interface maken wanneer we de constructor van de TShipBuilder klasse aanroepen.<\/p>\n<p>Zoals bij de meeste voorbeelden die ik eerder heb laten zien, moet je je ervan bewust zijn dat je de interfaces en classes niet allemaal in hetzelfde bestand moet zetten. Het is enkel omwille van de leesbaarheid dat ze nu even op \u00e9\u00e9n plaats staan.<\/p>\n<p>Samenvattend: om het Open\/Closed principe in Delphi te gebruiken heb je interfaces nodig om een class open te maken voor uitbreidingen en gebruik je het (strikte) private keyword om de class te sluiten voor wijzigingen. Gebruik zo weinig mogelijk overerving, want met overerving loop je het risico de class open te stellen voor modificaties. En onthoud: programmeer altijd tegen interfaces in plaats van implementaties.<\/p>\n","protected":false},"featured_media":0,"parent":0,"template":"","class_list":["post-2502","knowledge","type-knowledge","status-publish","hentry","knowledge-category-delphi","knowledge-category-software-ontwikkeling"],"acf":{"author":1398,"type_hero":"compact","hero_image":2499,"hero_image_position":"","hero_title":"SOLID Principes in Delphi [2] - Het Open\/Gesloten principe","hero_content":"","hero_link":null,"hero_show_h1":false},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.8 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>SOLID Principes in Delphi [2] - Het Open\/Closed principe - GDK Software<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/gdksoftware.com\/nl\/kennisbank\/solid-principles-in-delphi-2-the-open-closed-principle\" \/>\n<meta property=\"og:locale\" content=\"nl_NL\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"SOLID Principes in Delphi [2] - Het Open\/Closed principe\" \/>\n<meta property=\"og:description\" content=\"Het tweede principe van SOLID is het Open\/Closed principe: &#8220;Klassen en andere entiteiten moeten open zijn voor uitbreiding, maar gesloten voor wijziging&#8221;. Dit artikel gaat over hoe je in Delphi een klasse gesloten houdt voor modificatie, maar open voor uitbreiding. Laat ik \u00e9\u00e9n onderdeel benadrukken; dit doel bereiken via overerving of het overriden van classes [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/gdksoftware.com\/nl\/kennisbank\/solid-principles-in-delphi-2-the-open-closed-principle\" \/>\n<meta property=\"og:site_name\" content=\"GDK Software\" \/>\n<meta property=\"article:modified_time\" content=\"2021-03-25T10:01:25+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Geschatte leestijd\" \/>\n\t<meta name=\"twitter:data1\" content=\"4 minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/gdksoftware.com\\\/nl\\\/kennisbank\\\/solid-principles-in-delphi-2-the-open-closed-principle\",\"url\":\"https:\\\/\\\/gdksoftware.com\\\/nl\\\/kennisbank\\\/solid-principles-in-delphi-2-the-open-closed-principle\",\"name\":\"SOLID Principes in Delphi [2] - Het Open\\\/Closed principe - GDK Software\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gdksoftware.com\\\/nl#website\"},\"datePublished\":\"2021-01-28T18:01:00+00:00\",\"dateModified\":\"2021-03-25T10:01:25+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/gdksoftware.com\\\/nl\\\/kennisbank\\\/solid-principles-in-delphi-2-the-open-closed-principle#breadcrumb\"},\"inLanguage\":\"nl-NL\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/gdksoftware.com\\\/nl\\\/kennisbank\\\/solid-principles-in-delphi-2-the-open-closed-principle\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/gdksoftware.com\\\/nl\\\/kennisbank\\\/solid-principles-in-delphi-2-the-open-closed-principle#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/gdksoftware.com\\\/nl\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Knowledgebase\",\"item\":\"https:\\\/\\\/gdksoftware.com\\\/nl\\\/kennisbank\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Software ontwikkeling\",\"item\":\"https:\\\/\\\/gdksoftware.com\\\/nl\\\/kennisbank-categorie\\\/software-ontwikkeling\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"SOLID Principes in Delphi [2] &#8211; Het Open\\\/Closed principe\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/gdksoftware.com\\\/nl#website\",\"url\":\"https:\\\/\\\/gdksoftware.com\\\/nl\",\"name\":\"GDK Software\",\"description\":\"Zet de stip op je horizon\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/gdksoftware.com\\\/nl?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"nl-NL\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"SOLID Principes in Delphi [2] - Het Open\/Closed principe - GDK Software","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/gdksoftware.com\/nl\/kennisbank\/solid-principles-in-delphi-2-the-open-closed-principle","og_locale":"nl_NL","og_type":"article","og_title":"SOLID Principes in Delphi [2] - Het Open\/Closed principe","og_description":"Het tweede principe van SOLID is het Open\/Closed principe: &#8220;Klassen en andere entiteiten moeten open zijn voor uitbreiding, maar gesloten voor wijziging&#8221;. Dit artikel gaat over hoe je in Delphi een klasse gesloten houdt voor modificatie, maar open voor uitbreiding. Laat ik \u00e9\u00e9n onderdeel benadrukken; dit doel bereiken via overerving of het overriden van classes [&hellip;]","og_url":"https:\/\/gdksoftware.com\/nl\/kennisbank\/solid-principles-in-delphi-2-the-open-closed-principle","og_site_name":"GDK Software","article_modified_time":"2021-03-25T10:01:25+00:00","twitter_card":"summary_large_image","twitter_misc":{"Geschatte leestijd":"4 minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/gdksoftware.com\/nl\/kennisbank\/solid-principles-in-delphi-2-the-open-closed-principle","url":"https:\/\/gdksoftware.com\/nl\/kennisbank\/solid-principles-in-delphi-2-the-open-closed-principle","name":"SOLID Principes in Delphi [2] - Het Open\/Closed principe - GDK Software","isPartOf":{"@id":"https:\/\/gdksoftware.com\/nl#website"},"datePublished":"2021-01-28T18:01:00+00:00","dateModified":"2021-03-25T10:01:25+00:00","breadcrumb":{"@id":"https:\/\/gdksoftware.com\/nl\/kennisbank\/solid-principles-in-delphi-2-the-open-closed-principle#breadcrumb"},"inLanguage":"nl-NL","potentialAction":[{"@type":"ReadAction","target":["https:\/\/gdksoftware.com\/nl\/kennisbank\/solid-principles-in-delphi-2-the-open-closed-principle"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/gdksoftware.com\/nl\/kennisbank\/solid-principles-in-delphi-2-the-open-closed-principle#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/gdksoftware.com\/nl"},{"@type":"ListItem","position":2,"name":"Knowledgebase","item":"https:\/\/gdksoftware.com\/nl\/kennisbank"},{"@type":"ListItem","position":3,"name":"Software ontwikkeling","item":"https:\/\/gdksoftware.com\/nl\/kennisbank-categorie\/software-ontwikkeling"},{"@type":"ListItem","position":4,"name":"SOLID Principes in Delphi [2] &#8211; Het Open\/Closed principe"}]},{"@type":"WebSite","@id":"https:\/\/gdksoftware.com\/nl#website","url":"https:\/\/gdksoftware.com\/nl","name":"GDK Software","description":"Zet de stip op je horizon","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/gdksoftware.com\/nl?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"nl-NL"}]}},"_links":{"self":[{"href":"https:\/\/gdksoftware.com\/nl\/wp-json\/wp\/v2\/knowledge\/2502","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gdksoftware.com\/nl\/wp-json\/wp\/v2\/knowledge"}],"about":[{"href":"https:\/\/gdksoftware.com\/nl\/wp-json\/wp\/v2\/types\/knowledge"}],"acf:post":[{"embeddable":true,"href":"https:\/\/gdksoftware.com\/nl\/wp-json\/wp\/v2\/team\/1398"}],"wp:attachment":[{"href":"https:\/\/gdksoftware.com\/nl\/wp-json\/wp\/v2\/media?parent=2502"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}