{"id":1036,"date":"2026-03-19T17:02:23","date_gmt":"2026-03-19T20:02:23","guid":{"rendered":"https:\/\/adrianosantostreina.com.br\/blog\/?p=1036"},"modified":"2026-03-19T17:02:24","modified_gmt":"2026-03-19T20:02:24","slug":"poo-delphi-heranca-polimorfismo-exemplos","status":"publish","type":"post","link":"https:\/\/adrianosantostreina.com.br\/blog\/poo-delphi-heranca-polimorfismo-exemplos\/","title":{"rendered":"POO em Delphi: Heran\u00e7a, Polimorfismo e Exemplos Pr\u00e1ticos"},"content":{"rendered":"<h1>POO em Delphi: Heran\u00e7a, Polimorfismo e Exemplos Pr\u00e1ticos<\/h1>\n<section>\n<h2>Introdu\u00e7\u00e3o<\/h2>\n<p>Programa\u00e7\u00e3o Orientada a Objetos (POO) \u00e9 fundamental para desenvolver software organizado, test\u00e1vel e manuten\u00edvel em Delphi. Este artigo apresenta conceitos centrais de POO aplicados ao Object Pascal, com \u00eanfase em heran\u00e7a, polimorfismo, encapsulamento e boas pr\u00e1ticas de design conforme o livro Clean Code. Inclu\u00edmos exemplos completos e compil\u00e1veis, demonstrando como declarar m\u00e9todos virtuais na classe base e sobrescrev\u00ea-los nos descendentes (override). Ao seguir as normas de codifica\u00e7\u00e3o sugeridas \u2014 como prefixo F para campos privados, nomes descritivos e responsabilidade \u00fanica das classes \u2014 voc\u00ea obter\u00e1 c\u00f3digo mais claro e duradouro.<\/p>\n<\/section>\n<section>\n<h2>Conceitos fundamentais de POO no Delphi<\/h2>\n<p>Nesta se\u00e7\u00e3o recapitulamos defini\u00e7\u00f5es essenciais: classe, objeto, heran\u00e7a, polimorfismo e encapsulamento. No Delphi, classes s\u00e3o tipos de refer\u00eancia derivados de TObject; m\u00e9todos podem ser declarados como virtual\/abstract para permitir sobrescrita (override) em descendentes. Encapsulamento \u00e9 obtido com se\u00e7\u00f5es private\/protected\/public e propriedades que controlam o acesso a campos internos.<\/p>\n<\/section>\n<section>\n<h2>Classes e objetos: conven\u00e7\u00f5es e estrutura<\/h2>\n<p>Use nomes claros e PascalCase para classes e m\u00e9todos, prefira campos privados com prefixo F, e exponha apenas o necess\u00e1rio via propriedades e m\u00e9todos p\u00fablicos. Declare m\u00e9todos que poder\u00e3o ser sobrescritos como virtual na classe base. Concentre responsabilidades para favorecer testes e manuten\u00e7\u00e3o.<\/p>\n<h3>Exemplo: assinatura de uma classe base<\/h3>\n<p>O exemplo abaixo mostra uma estrutura adequada de classe base com m\u00e9todos virtuais que podem ser sobrescritos por classes filhas.<\/p>\n<pre><code>unit BankAccounts;\n\ninterface\n\nuses\n  System.SysUtils;\n\ntype\n  TAccount = class\n  private\n    FOwner: string;\n  protected\n    FBalance: Currency; \/\/ protected para permitir uso em descendentes\n    procedure SetBalance(const Value: Currency); virtual;\n  public\n    constructor Create(const AOwner: string; AInitialBalance: Currency = 0); virtual;\n    procedure Deposit(const Amount: Currency); virtual;\n    procedure Withdraw(const Amount: Currency); virtual;\n    function GetBalance: Currency; virtual;\n    property Owner: string read FOwner write FOwner;\n    property Balance: Currency read FBalance write SetBalance;\n  end;\n\nimplementation\n\n{ implementa\u00e7\u00e3o omitida aqui }\n\nend.<\/code><\/pre>\n<\/section>\n<section>\n<h2>Heran\u00e7a e Polimorfismo<\/h2>\n<p>Heran\u00e7a permite que classes compartilhem comportamento; polimorfismo permite tratar objetos de tipos diferentes como inst\u00e2ncias da mesma base, chamando o m\u00e9todo apropriado em tempo de execu\u00e7\u00e3o. Em Delphi, isso depende de m\u00e9todos declarados virtual na base e override nos descendentes.<\/p>\n<h3>Exemplo pr\u00e1tico: contas banc\u00e1rias<\/h3>\n<p>Segue um exemplo completo e compil\u00e1vel de uma unidade com TAccount (base), TSavingsAccount (poupan\u00e7a) e TCheckingAccount (corrente). Observe que m\u00e9todos que s\u00e3o sobrescritos s\u00e3o declarados virtual na classe base.<\/p>\n<pre><code>unit BankAccounts;\n\ninterface\n\nuses\n  System.SysUtils;\n\ntype\n  EAccountException = class(Exception);\n\n  TAccount = class\n  private\n    FOwner: string;\n  protected\n    FBalance: Currency;\n    procedure SetBalance(const Value: Currency); virtual;\n  public\n    constructor Create(const AOwner: string; AInitialBalance: Currency = 0); virtual;\n    procedure Deposit(const Amount: Currency); virtual;\n    procedure Withdraw(const Amount: Currency); virtual;\n    function GetBalance: Currency; virtual;\n    property Owner: string read FOwner write FOwner;\n    property Balance: Currency read FBalance write SetBalance;\n  end;\n\n  TSavingsAccount = class(TAccount)\n  private\n    FInterestRate: Double;\n  public\n    constructor Create(const AOwner: string; AInitialBalance: Currency; AInterestRate: Double); reintroduce;\n    procedure ApplyInterest; virtual;\n    procedure Withdraw(const Amount: Currency); override;\n  end;\n\n  TCheckingAccount = class(TAccount)\n  private\n    FOverdraftLimit: Currency;\n  public\n    constructor Create(const AOwner: string; AInitialBalance: Currency; AOverdraftLimit: Currency); reintroduce;\n    procedure Withdraw(const Amount: Currency); override;\n    property OverdraftLimit: Currency read FOverdraftLimit write FOverdraftLimit;\n  end;\n\nimplementation\n\n{ TAccount }\n\nconstructor TAccount.Create(const AOwner: string; AInitialBalance: Currency);\nbegin\n  inherited Create;\n  FOwner := AOwner;\n  FBalance := AInitialBalance;\nend;\n\nprocedure TAccount.SetBalance(const Value: Currency);\nbegin\n  FBalance := Value;\nend;\n\nprocedure TAccount.Deposit(const Amount: Currency);\nbegin\n  if Amount <= 0 then\n    raise EArgumentException.Create('Amount must be positive.');\n  FBalance := FBalance + Amount;\nend;\n\nprocedure TAccount.Withdraw(const Amount: Currency);\nbegin\n  if Amount <= 0 then\n    raise EArgumentException.Create('Amount must be positive.');\n  if Amount > FBalance then\n    raise EAccountException.Create('Insufficient funds.');\n  FBalance := FBalance - Amount;\nend;\n\nfunction TAccount.GetBalance: Currency;\nbegin\n  Result := FBalance;\nend;\n\n{ TSavingsAccount }\n\nconstructor TSavingsAccount.Create(const AOwner: string; AInitialBalance: Currency; AInterestRate: Double);\nbegin\n  inherited Create(AOwner, AInitialBalance);\n  FInterestRate := AInterestRate;\nend;\n\nprocedure TSavingsAccount.ApplyInterest;\nbegin\n  FBalance := FBalance + (FBalance * FInterestRate \/ 100);\nend;\n\nprocedure TSavingsAccount.Withdraw(const Amount: Currency);\nbegin\n  \/\/ Poupan\u00e7a n\u00e3o permite overdraft; reutiliza valida\u00e7\u00e3o da base\n  inherited Withdraw(Amount);\nend;\n\n{ TCheckingAccount }\n\nconstructor TCheckingAccount.Create(const AOwner: string; AInitialBalance: Currency; AOverdraftLimit: Currency);\nbegin\n  inherited Create(AOwner, AInitialBalance);\n  FOverdraftLimit := AOverdraftLimit;\nend;\n\nprocedure TCheckingAccount.Withdraw(const Amount: Currency);\nbegin\n  if Amount <= 0 then\n    raise EArgumentException.Create('Amount must be positive.');\n  if Amount > (FBalance + FOverdraftLimit) then\n    raise EAccountException.Create('Exceeds overdraft limit.');\n  FBalance := FBalance - Amount;\nend;\n\nend.<\/code><\/pre>\n<h3>Uso polim\u00f3rfico<\/h3>\n<p>Exemplo de uso em um projeto console demonstrando polimorfismo: manipular TAccount referenciando objetos de tipos derivados.<\/p>\n<pre><code>program DemoAccounts;\n\nuses\n  System.SysUtils, BankAccounts;\n\nvar\n  Acc: TAccount;\nbegin\n  Acc := TSavingsAccount.Create('Alice', 1000.00, 1.5);\n  try\n    Acc.Deposit(500);\n    Acc.Withdraw(200);\n    Writeln('Saldo: ' + CurrToStr(Acc.GetBalance)); \/\/ chama o m\u00e9todo apropriado\n  finally\n    Acc.Free;\n  end;\nend.<\/code><\/pre>\n<\/section>\n<section>\n<h2>Encapsulamento e propriedades<\/h2>\n<p>Propriedades controlam acesso a campos internos; use setters\/getters para valida\u00e7\u00f5es. Mantenha campos com prefixo F e evite acesso p\u00fablico direto para preservar invariantes da classe.<\/p>\n<\/section>\n<section>\n<h2>Boas pr\u00e1ticas e Clean Code aplicadas ao Delphi<\/h2>\n<p>Adote nomes claros, m\u00e9todos curtos, uma responsabilidade por classe, e coment\u00e1rios s\u00f3 quando o c\u00f3digo n\u00e3o for autoexplicativo. Separe interfaces e implementa\u00e7\u00f5es, prefira propriedades em vez de campos p\u00fablicos e documente pr\u00e9-condi\u00e7\u00f5es e exce\u00e7\u00f5es. Estas pr\u00e1ticas facilitam manuten\u00e7\u00e3o e testes.<\/p>\n<h3>Dicas concretas<\/h3>\n<p>&#8211; Prefira nomes como Deposit, Withdraw em vez de Dep, W; &#8211; Use exce\u00e7\u00f5es espec\u00edficas para estados de erro; &#8211; Declare virtual apenas quando necess\u00e1rio; &#8211; Evite duplica\u00e7\u00e3o de l\u00f3gica entre classes.<\/p>\n<\/section>\n<section>\n<h2>Depura\u00e7\u00e3o, testes e valida\u00e7\u00e3o<\/h2>\n<p>Crie testes unit\u00e1rios cobrindo comportamento polim\u00f3rfico e casos de exce\u00e7\u00e3o. Ao debugar, examine chamadas virtuais e verifique se o m\u00e9todo esperado foi executado. Use Test Frameworks como DUnitX para automatizar verifica\u00e7\u00e3o de contratos (pr\u00e9 e p\u00f3s-condi\u00e7\u00f5es).<\/p>\n<\/section>\n<section>\n<h2>#Dica do Mestre<\/h2>\n<p>Se voc\u00ea mencionar tecnologias adjacentes (UML, REST, JSON) que n\u00e3o s\u00e3o foco central deste artigo, considere que UML \u00e9 uma linguagem de modelagem para descrever classes e rela\u00e7\u00f5es. Consulte a documenta\u00e7\u00e3o e guias externos para aprofundamento: UML (https:\/\/en.wikipedia.org\/wiki\/Unified_Modeling_Language). Para documenta\u00e7\u00e3o oficial do Delphi e unidades de runtime, consulte a DocWiki da Embarcadero: https:\/\/docwiki.embarcadero.com\/RADStudio\/en\/ e a p\u00e1gina da unit System.Classes: https:\/\/docwiki.embarcadero.com\/Libraries\/en\/System.Classes.<\/p>\n<\/section>\n<section>\n<h2>Imagem de Capa<\/h2>\n<p>Abaixo est\u00e1 uma imagem de capa gerada em SVG monocrom\u00e1tica em tom pastel. Use-a como thumbnail para publica\u00e7\u00f5es.<\/p>\n<div>\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"1200\" height=\"630\" viewBox=\"0 0 1200 630\" role=\"img\" aria-label=\"Capa POO Delphi\">\n      <rect width=\"1200\" height=\"630\" fill=\"#C7E6A7\" \/>\n      <g fill=\"#284b2b\" font-family=\"Segoe UI, Arial, sans-serif\">\n        <text x=\"60\" y=\"180\" font-size=\"64\" font-weight=\"700\">POO em Delphi<\/text>\n        <text x=\"60\" y=\"260\" font-size=\"28\">Heran\u00e7a, Polimorfismo e Boas Pr\u00e1ticas<\/text>\n      <\/g>\n      <g transform=\"translate(850,370)\" fill=\"#284b2b\" opacity=\"0.12\">\n        <rect x=\"0\" y=\"0\" width=\"280\" height=\"180\" rx=\"14\" \/>\n      <\/g>\n    <\/svg>\n  <\/div>\n<p>Cor da Imagem: #C7E6A7 (pastel verde)<\/p>\n<\/section>\n<section>\n<h2>Refer\u00eancias e leituras recomendadas<\/h2>\n<p>Consulte a DocWiki da Embarcadero para refer\u00eancia de runtime e classes: https:\/\/docwiki.embarcadero.com\/RADStudio\/en\/. Para padr\u00f5es de projeto e Clean Code, consulte os livros correspondentes e adapte os princ\u00edpios ao Object Pascal.<\/p>\n<\/section>\n<section>\n<h2>Conclus\u00e3o<\/h2>\n<p>A POO em Delphi oferece recursos poderosos de modelagem quando usados com disciplina: declare m\u00e9todos virtual na classe base, sobrescreva com override nas classes filhas, mantenha encapsulamento e siga regras de Clean Code. Os exemplos apresentados demonstram como projetar hierarquias seguras e test\u00e1veis, al\u00e9m de aplicar padr\u00f5es simples que facilitam evolu\u00e7\u00e3o do c\u00f3digo. Pratique escrevendo pequenas hierarquias, adicionando testes unit\u00e1rios e revisando seu design conforme surgem novas responsabilidades.<\/p>\n<\/section>\n","protected":false},"excerpt":{"rendered":"<p>POO em Delphi: Heran\u00e7a, Polimorfismo e Exemplos Pr\u00e1ticos Introdu\u00e7\u00e3o Programa\u00e7\u00e3o Orientada a Objetos (POO) \u00e9 fundamental para desenvolver software organizado, test\u00e1vel e manuten\u00edvel em Delphi. Este artigo apresenta conceitos centrais de POO aplicados ao Object Pascal, com \u00eanfase em heran\u00e7a, polimorfismo, encapsulamento e boas pr\u00e1ticas de design conforme o livro Clean Code. Inclu\u00edmos exemplos completos [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1036","post","type-post","status-publish","format-standard","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/1036","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/comments?post=1036"}],"version-history":[{"count":1,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/1036\/revisions"}],"predecessor-version":[{"id":1045,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/1036\/revisions\/1045"}],"wp:attachment":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/media?parent=1036"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/categories?post=1036"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/tags?post=1036"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}