Sei sulla pagina 1di 46

2017

Introdução a
Orientação a Objetos
com Delphi

POO NO DELPHI VAI ALÉM DA HERANÇA E DO


POLIMORFISMO
RODRIGO MOURÃO

RM FACTORY | Rio de Janeiro - RJ


SUMÁRIO
História .................................................................................................. 1
O que houve de errado com o SIMULA? .................................. 3
Se Tratando de Delphi Language .............................................. 4
Introdução ao Mundo Orientado a Objetos ............................... 6
Classes e Objetos ........................................................................... 6
Declarações Forward ................................................................... 9
Meta Classes ................................................................................. 10
Herança ......................................................................................... 11
Herança por Associação ........................................................... 12
Interfaces ....................................................................................... 13
Implements .................................................................................... 18
Polimorfismo .................................................................................. 19
Override e Method Hides ........................................................... 21
Polimorfismo Tácito. Pensando em “Cadeia Polimórfica” . 22
Virtual ou Dynamic, eis a questão!........................................... 24
Sobrecarga de Métodos ............................................................ 25
Métodos Abstratos ....................................................................... 27
Type Casts ..................................................................................... 28
Encapsulamento .......................................................................... 29
Get e Sets ...................................................................................... 31
O Operador Index ....................................................................... 32
Propriedades Indexadas ............................................................ 33
Default, NoDefault e Stored ....................................................... 35
Encapsulamento e Classes Amigas ......................................... 36
Data Access Objetc - DAO ........................................................... 36
Estrutura DAO................................................................................ 37
BusinessObject 37
DataAccessObject ...................................................................... 37
DataSource ................................................................................... 38
TransferObject .............................................................................. 38
1 Introdução a Orientação a Objetos com Delphi

PROGRAMAÇÃO
ORIENTADA A OBJETOS
HISTÓRIA

A
ntes de tudo, é muito importante esclarecer que
o termo OOP ou Object-Oriented Programming
não se aplica somente a um modelo de
programação, e muito menos se restringe a paradigmas como
herança, polimorfismo e encapsulamento. OOP é um conceito
muito mais amplo do que imaginamos, e muito mais complexo.
Por mais estranho que pareça ser, a ideia da Orientação a
Objetos surgiu através das primeiras linguagens a usar este
conceito, SIMULA I entre (1962-1965) e SIMULA 67 (1967). O
Simula 67 (SIMUlation LAnguage) empregou os principais
pontos chave da orientação a objetos, classes e objetos,
herança, métodos virtuais. A linguagem Simula foi
desenvolvida no Centro Norueguês de Computação em Oslo,
Noruega, por Ole-Johan Dahl e Kristen Nygaard.

O trabalho de Nygaard na Pesquisa Operacional nos


anos de 1950 e mais tarde em 1960 criou a necessidade por
ferramentas precisas para a descrição e simulação de sistemas
complexos homem- máquina. Em 1961 a ideia surgiu

portal.rmfactory.com.br
2 Introdução a Orientação a Objetos com Delphi

desenvolvendo uma linguagem poderia ser usada para


descrição de sistemas (por pessoas) e para prescrição de
sistemas (como um programa de computador através de um
compilador). Tal linguagem tem que conter uma linguagem
algorítmica e o conhecimento de Dahl em compiladores
torna-se essencial.

O compilador do SIMULA I foi parcialmente financiado


pela UNIVAC e estava pronto em janeiro de 1965. SIMULA I
rapidamente começou uma reputação como uma linguagem
de programação de simulação.

Quando o mecanismo de herança foi inventado em


1967, o Simula 67 foi desenvolvido como uma linguagem de
programação de uso geral, que também poderia ser utilizada
em várias áreas, inclusive no sistema de simulação.
Compiladores Simula 67 começou a aparecer em
computadores UNIVAC, IBM, Control Data, Burroughs, DEC e
em outros mais tarde na década de 70.

O Simula 67 foi usado por várias pessoas a redor do


mundo, mas o principal impacto aconteceu através da
introdução de uma das principais categorias da
programação, mais conhecida como object-oriented
programming. Os conceitos do Simula foram importantes na
discussão de tipos de dados abstratos e dos modelos para a
execução de programa concorrente, começando no
princípio dos anos 70.

O Simula 67 e as modificações do Simula foram usados no


projeto de circuitos do VLSI (Intel, Caltech, Stanford). O grupo
de Alan Kay em Xerox PARC usou Simula como uma
plataforma para seu desenvolvimento do Smalltalk (primeira
versão da linguagem em 1970), estendendo a programação
orientada a objetos importantemente pela integração de
interfaces de usuário gráficas e a execução interativa de um
programa.

portal.rmfactory.com.br
3 Introdução a Orientação a Objetos com Delphi

Bjarne Stroustrup começou seu desenvolvimento do C++


(nos 80) trazendo os conceitos chaves do Simula na linguagem
de programação de C. Simula inspirou também muito trabalho
na área do reuso de componente do programa e na
construção de bibliotecas.

Figura 1 - Bjarne Stroustrup, criador do C++

Figura 2 - IDE do SmallTalk

O QUE HOUVE DE ERRADO COM O SIMULA?

Simula nunca tornou-se uma linguagem de programação


extensamente usada. Existem várias razões que explicam este
fato:

Gerais:

• Nasceu em um pequeno país Europeu

portal.rmfactory.com.br
4 Introdução a Orientação a Objetos com Delphi

• Congelado em 1968
• Caro
• Não tem uma IDE moderna
• Muito complicado
• Publicações insuficientes

Características da linguagem:

• Facilidades limitadas de acesso a arquivos


• Ausência de tipos de dados (records, sets)
• Sem paralelismo avançado e suporte em tempo real.
• Sem suporte a interface gráfica GUI
• Pesados executáveis para pequenos programas

Características OOP:

• Sem suporte a herança múltipla


• Sem suporte a interfaces

Simulação:

• Sem suporte automático de coleção de estatísticas.


• Sem suporte a relatórios
• Ausência de facilidades especializadas (resources)

SE TRATANDO DE DELPHI LANGUAGE

O primeiro compilador Pascal foi desenvolvido em


Zurique para a família de computadores CDC 6000, sendo
lançado em 1970. Também em 1970 foi desenvolvido o
primeiro compilador Pascal norte americano, na Universidade
de Illinois por Donald B. Gillies, que gerava código de máquina
nativo para o minicomputador PDP-11.

Pensando-se em propagar rapidamente o uso da


linguagem, foi criado, em Zurique, um "kit de conversão" que
incluía um compilador que gerava código intermediário, e um

portal.rmfactory.com.br
5 Introdução a Orientação a Objetos com Delphi

simulador para ele. Esse kit foi batizado de p-System, e foi


utilizado, entre outras coisas, para criar um sistema operacional
para minicomputadores chamado UCSD p-System,
desenvolvido pelo Instituto de Sistemas de Informação da
Universidade da Califórnia em San Diego. Segundo o próprio
Niklaus Wirth, o p-System e o UCSD foram instrumentais na
popularização do Pascal.

Nos anos 80, Anders Hejlsberg desenvolveu o compilador


Blue Label Pascal o Nascom-2. Depois, ele foi trabalhar na
Borland e reescreveu seu compilador transformando-o no
Turbo Pascal para a plataforma IBM PC (e também CP/M 80),
que era vendido a US$ 49,95, muito mais barato do que o Blue
Label. Uma característica muito importante é que o Turbo
Pascal é uma linguagem compilada, que gera código de
máquina real para a arquitetura Intel 8088, tornando-a muito
mais rápida do que as linguagens interpretadas.

Por ser mais barato, o Turbo Pascal passou a ter uma


grande influência na comunidade Pascal, que começou a se
concentrar na plataforma IBM PC no fim dos anos 80. Muitos
usuários de PC da época migraram para o Turbo Pascal, em
busca de uma linguagem estruturada que não fosse
interpretada, para substituir, por exemplo, o BASIC. Pode se
afirmar que o sucesso comercial de Turbo Pascal foi definitivo
para a ampla divulgação da linguagem Pascal entre os
usuários de microcomputador.

Outra variante era o Super Pascal, que adicionava labels


não numéricas, o comando return e expressões como nomes
de tipos.

Durante os anos 90, compiladores que podiam ser


modificados para trabalhar com arquiteturas diferentes
tiveram grande destaque, incluindo nessa lista o Pascal.

O próximo grande passo para a linguagem, foi a


implementação da orientação a objeto (OO ou OOP em

portal.rmfactory.com.br
6 Introdução a Orientação a Objetos com Delphi

inglês) na sua estrutura, começando com a versão 5.5 do Turbo


Pascal. Mais tarde, ao projetar o Delphi, querendo
funcionalidades mais elaboradas da orientação a objeto, a
Borland utilizou o conceito Object Pascal criado pela Apple,
utilizando-o como base para uma nova linguagem, que nas
versões iniciais era chamado de Object Pascal foi rebatizado
como Delphi Programming Language nas versões posteriores.
As maiores diferenças em relação às implementações OO das
versões mais antigas foram a adição do conceito de objetos
por referência, construtores, destrutores e propriedades, entre
outros.

Lembre-se sempre que dominar os paradigmas da


orientação a objetos como herança e polimorfismo não o fará
objetivamente, um programador orientado a objetos.

INTRODUÇÃO AO MUNDO ORIENTADO A


OBJETOS

C
ostumo dizer que a orientação a objetos não é a
solução para todos os problemas. Há um ditado
que retrata muito bem isto: "quando a única
ferramenta que temos na mão é um martelo, tudo vira prego".
A ideia da OOP é agregar a modelos de programação
estruturados e modular paradigmas que trazem benefícios
objetivos.

[FIGURA DOS PILARES DA POO]

CLASSES E OBJETOS
Eu poderia aqui fazer uma grande dissertação
acadêmica falando de classes e objetos, os comparando a
bolos, carros, pessoas etc. Acredito que depois de mais de 30

portal.rmfactory.com.br
7 Introdução a Orientação a Objetos com Delphi

anos ninguém agüenta mais tais analogias. Classes


representam o protótipo para objetos em memória (instância).
Classes determinam todo o comportamento de um objeto, em
outras palavras um objeto é uma representação “física” de
uma classe, assim como uma edificação é a representação de
uma planta.

A principal motivação que impulsiona a orientação a


objetos é a criação de classes que representam uma
funcionalidade específica, uma tarefa determinada, ou seja,
para cada classe um objeto, para cada objeto uma
responsabilidade.

Uma classe deve possuir uma classe ancestral


obrigatoriamente, contudo no Delphi não é necessário
declarar esta herança explicitamente, pois qualquer classe
quando declarada sem sua classe ancestral,
automaticamente herda da classe TObject, que é a classe
progenitora de todas as classes que compõem a VCL.

Um protótipo de objeto (classe) pode ser composta de


campos (Fields), propriedades (property) e métodos
(procedures e functions).

Toda classe deve possuir ao menos dois métodos, um


método construtor e outro destrutor. Os métodos construtores
de uma classe são declarados através da palavra reservada
“constructor” e geralmente são chamados de “Create”.
Métodos construtores são métodos especializados, pois
alocam toda a memória necessária à criação (instanciação)
de um objeto, retorna a referência para este objeto, e é o local
recomendado para inicialização de campos, onde todos os
membros são inicializados com “nil” ou string vazia.

Dica: caso algo de errado aconteça durante a


construção do objeto “constructor” automaticamente seu
método destrutor será invocado.

portal.rmfactory.com.br
8 Introdução a Orientação a Objetos com Delphi

Mas ao ser observado a estrutura do construtor na classe


base TObject, será constatado que o mesmo não possui
instrução alguma:
constructor TObject.Create;
begin
end;
Todo construtor automaticamente chama o método
NewInstance da classe TObject que invoca o método
InitInstance. Por sua vez, InitInstance usa a função InstanceSize
do objeto para determinar quanto em bytes é necessário para
alocar memória para o objeto. Nunca o método NewInstance
ou InitInstance deverão ser invocados diretamente.
class function NewInstance: TObject; virtual;

class function InitInstance(Instance: Pointer):


TObject;

class function InstanceSize: Longint;

Observe que o método NewInstance é virtual, portanto


pode ser sobreposto em situações onde houver a necessidade
de modificação da forma com os recursos (memória) são
alocados. Uma vez que o NewInstance seja sobreposto para
customização da alocação de memória, o FreeInstance
também deverá ser sobreposto, pois os recursos alocados
precisam ser dispensados.

Contudo, no “frigir dos ovos” objetivamente, não é o


método “Create” quem aloca memória diretamente, ele é
apenas um estimulador automático dos métodos NewInstance
e InitInstance.

O método destrutor de uma classe tem um papel inverso


ao construtor, sua tarefa é desalocar os recursos que o
construtor demandou. Todo método destrutor de um objeto
chama automaticamente o método FreeInstance usa

portal.rmfactory.com.br
9 Introdução a Orientação a Objetos com Delphi

também o InstanceSize para dispensar a memória alocada


pelo NewInstance para o objeto.

Contudo isto, se justifica que os métodos construtor e


destrutor de TObject estejam vazios, pois são apenas
encadeadores dos verdadeiros métodos que realizam as
tarefas de alocar e desalocar memória para os objetos.

DECLARAÇÕES FORWARD
Frequentemente quando trabalhamos com classes é
comum nos depararmos com a situações de mútua
dependência, ou seja, duas classes que fazem referência uma
as outras:
TClassA = class
B: TclassB; //erro aqui!
end;

TclassB = class
A: TclassA;
end;

Um erro em tempo de desenvolvimento seria exibido, pois


a classe TclassA “usa” (associação) a classe TclassB que está
declara após a classe, ou seja, o compilador ainda não
“tomou ciência” da existência da classe TclassB, pois a
compilação é top-down (de cima para baixo).

Para resolver esta “mútua dependência”, usamos uma


declaração “forward” acima da classe TclassA:
TclassB = class; //declaração forward

TClassA = class
B: TClassB;
end;

portal.rmfactory.com.br
10 Introdução a Orientação a Objetos com Delphi

TClassB = class
A: TclassA;
end;

É muito comum confundir declarações forward com a de


classes do tipo TSample = class end. São coisas totalmente
distintas.

META CLASSES
Meta Classes são estruturas referência para classes, que
podem ser utilizadas no código para aumentar a flexibilidade.
A declaração de um “tipo referência de classe” é feita através
da diretiva “class of”.
TMetaCliente = class of TCliente;

Com isto, agora temos em TMetaCliente, uma referência


a classe TCliente, ou seja, TMetaCliente poderá ser exigido em
operações que exijam o tipo da classe e não sua instancia.
Observe este exemplo prático:
type

TBaseClass = class
end;

TMetaBaseClass = class of TBaseClass;

TCliente = class(TBaseClass)
Nome: string;
end;

TFuncionario = class(TBaseClass)
Matricula: string;
end;

Observe que o construtor pode ser invocado através de


uma variável referência de classe.

portal.rmfactory.com.br
11 Introdução a Orientação a Objetos com Delphi

function TForm1.GetObjectInstance(Meta:
TMetaBaseClass): TBaseClass;
begin
result := Meta.Create;
end;

Com
isso podemos
criar instancias de
objetos
genéricos
sem conhecer
suas estruturas
originais.
var
Cliente: TCliente;
Funcionario: TFuncionario;
begin
Cliente:= GetObjectInstance(TCliente) as TCliente;
Funcionario := GetObjectInstance(TFuncionario) as
TFuncionario;
end;

HERANÇA
Herança realmente é um mecanismo poderoso da
orientação a objetos, mas objetivamente não é a panacéia
tecnológica. Neste observaremos que valorizam essa prática e
outras as quais ela trás prejuízos. Herança agrega evidente
reaproveitamento de código, onde verdadeira estruturas
codificadas podem se especializadas em uma nova classe.
Quando falamos em herança dois termos precisam ser
esclarecidos: Generalização e Especialização.

portal.rmfactory.com.br
12 Introdução a Orientação a Objetos com Delphi

Generalização é um grau de abstração de alto nível,


representada através de classes que servem de base
polimórfica e/ou de implementação para classes
descendentes. No Delphi isto está presente em toda a
arquitetura da VCL.

TAnimal – generalização de todas as classes que


descendem de TAnimal.

A Generalização pode ser classificada em três tipos:


disjunta, sobreposta, completa ou incompleta.

Especialização é a herança propriamente dita, quando


reaproveitamos estruturas já declaradas por uma classe
ancestral.

TDog é uma especialização de TAninal;

A especialização de uma classe é sempre total, ou seja,


ao herdar de uma determinada classe, você assumirá todos os
seus membros, sem exceção. Classes especializadas podem
ganhar flexibilidade adicional quando usada associada a
métodos não estáticos, que veremos em seguida.

A arquitetura da linguagem Delphi não foi projetada de


forma a permitir especializar mais de uma classe
simultaneamente “herança múltipla”. Acredito que esta regra
esteja em total conformidade com os paradigmas da
orientação a objetos.

HERANÇA POR ASSOCIAÇÃO

portal.rmfactory.com.br
13 Introdução a Orientação a Objetos com Delphi

Como coloquei no início do capítulo, a herança não é


solução para todos os problemas, o velho problema de
“martelos e pregos”. A herança atribui ao código uma
dependência forte entre as classes, o que chamamos de “forte
acoplamento”, o que contradiz ao paradigma da orientação
a objetos que prega que o código deve Ter “fraco
acoplamento”. Bom, o que isto significa objetivamente para o
programador? Forte acoplamento se traduz e dependências
que refletem e diversos efeitos colaterais no código fonte,
aquelas pequenas correções ou até mesmo melhorias que
encadeiam uma serie “bugs” em todo o projeto.

Efeitos colaterais são caracterizados por mudanças no


código que afetam o funcionamento de outras classes que
utilizam desta implementação. Um exemplo típico seria uma
classe que usa um serviço de uma outra classe que calcula um
determinado imposto. Na evolução do projeto, é muito
comum ocorrem mudanças, e uma destas mudanças afetou
a forma de como o imposto é calculado para uma única
situação específica. Ao altera este comportamento, você
atenderia a demanda específica, mas faria com que todas as
outras classes que utilizam deste serviço deixem de funcionar.

Para minimizar estes reflexos no código, devemos reduzir


o acoplamento entre as classes usando associações em vez
de herança. Associação entre classes estabelecem uma
relação lógica que é classificada de duas formas: Agregação
ou Composição.

INTERFACES

Interface é uma ferramenta da orientação a objetos


extremamente poderosa. Grande novidade no Delphi 3,
Interfaces propõem-se a estabelecer uma camada abstrata
que determina uma estrutura ou contrato para um objeto. Isto
significa que, analogamente a um exemplo real como a de

portal.rmfactory.com.br
14 Introdução a Orientação a Objetos com Delphi

construção de moradias, as necessidades expostas por um


processo licitatório seria nossa interface, ou seja, toda empresa
que desejasse participar do processo deverá estar em
conformidade com as necessidades determinadas no
documento de licitação. Com isto temos uma abstração total
de qual empresa “objeto” efetuará a tarefa.
ILicitacao = interface
procedure DocumentarProjetos;
procedure ElicitarRequisitos;
procedure ModelacaoUML;
end;

TEmpresaA = class(TinterfacedObject, Ilicitacao)


procedure DocumentarProjetos;
procedure ElicitarRequisitos;
procedure ModelacaoUML;
end;

TEmpresaB = class(TinterfacedObject, Ilicitacao)


procedure DocumentarProjetos;
procedure ElicitarRequisitos;
procedure ModelacaoUML;
end;

Neste exemplo, usamos uma interface que declara o


método ExecuteCalc, que será implementado por várias
classes, cada qual a sua necessidade.
type

ICalculator = interface
function ExecuteCalc(a,b: Double): Double;
end;

TSum = class(TInterfacedObject, ICalculator)


public
function ExecuteCalc(a, b: Double): Double;
end;

portal.rmfactory.com.br
15 Introdução a Orientação a Objetos com Delphi

TDivide = class(TInterfacedObject, ICalculator)


public
function ExecuteCalc(a, b: Double): Double;
end;

TMultiply = class(TInterfacedObject, ICalculator)


public
function ExecuteCalc(a, b: Double): Double;
end;

TSubtraction = class(TInterfacedObject, ICalculator)


public
function ExecuteCalc(a, b: Double): Double;
end;

implementation

uses

SysUtils;

function TSum.ExecuteCalc(a, b: Double): Double;


begin
result := a +b;
end;

function TDivide.ExecuteCalc(a, b: Double): Double;


begin
if b = 0 then
begin
result := 0;
raise Exception.Create('Divisão por Zero !!!!');
end
else
result := a / b;
end;

function TMultiply.ExecuteCalc(a, b: Double):


Double;
begin

portal.rmfactory.com.br
16 Introdução a Orientação a Objetos com Delphi

result := a * b;
end;

function TSubtraction.ExecuteCalc(a, b: Double):


Double;
begin
result := a - b;
end;

Cliente:
var
a, b, rSum, rMult: Double;
CalcSum, CalcMult: ICalculator;
begin
a := 10;
b := 20;
CalcSum := TSum.Create;
rSum := CalcSum.ExecuteCalc(a, b); //resultado da
soma
rMult := CalcMult.ExecuteCalc(a, b); //resultado
da multiplicação
end;

Costumo usar este exemplo com meus alunos, onde eu


digo: “...Eu quero um carro”. Com esta afirmativa eu coloquei
uma necessidade num contexto geral, não me preocupando
com os detalhes envolvidos no que eu pedia. Isto é uma
interface, ou seja, um veículo pra ser entendido como “carro”
precisa de requisitos mínimos, como pneus, motor, volante e
como diz minha mãe: “carro pro seu pai basta ter a ignição !”.
A afirmativa não detalhou “qual” carro se deseja, isso quer
dizer que qualquer objeto concreto (TMercedez) que tenha as
característica de um carro (ICarro) solucionaria nossa questão.

type

portal.rmfactory.com.br
17 Introdução a Orientação a Objetos com Delphi

ICarro = interface
procedure SetModelo(const Value: string);
function GetModelo: string;
procedure Ligar;
property Modelo: string read GetModelo write
SetModelo;
end;

TMercedez = class(TInterfacedObject, ICarro)


private
FModelo: string;
public
procedure SetModelo(const Value: string);
function GetModelo: string;
constructor Create;
published
procedure Ligar;
property Modelo: string read GetModelo write
SetModelo;
end;

Implementation

uses
Dialogs;

constructor TMercedez.Create;
begin

inherited;

FModelo := 'Mercedez';
end;

function TMercedez.GetModelo: string;


begin
result := FModelo;
end;

portal.rmfactory.com.br
18 Introdução a Orientação a Objetos com Delphi

procedure TMercedez.Ligar;
begin
ShowMessage('Motor ligado!');
end;

procedure TMercedez.SetModelo(const Value: string);


begin
FModelo := Value;
end;

Interfaces são componentes indispensáveis a uma boa


abstração e redução de acoplamento. Interfaces no Delphi
obedecem a uma hierarquia que tem como base a interface
Iinterface. Toda interface escrita em Delphi herda direta ou
indiretamente de IInterface, portanto, para uma interface que
terá um papel de automação (COM – Component Object
Model) deverá ter IUnknown como interface base. Esta divisão
hierárquica atende apenas para fins de organização, visto que
Iunknown é explicitamente equivalente a IInterface
IUnknown = IInterface;

Interfaces possuem um mecanismo de contagem de


referência, o que permite o autogerenciamento no que diz
respeito aos recursos de memória. Isto elimina a necessidade
de liberações explicitas de objetos através de Free, Destroy ou
FreeAndNil.

{codigo IInterface e métodos}

Interfaces são similares a classes abstratas, que possuem


métodos abstratos não implementados. Uma interface não
implementa método algum, ela apenas os declara, os publica,
deixando a cargo das classes concretas que os implementam.

IMPLEMENTS

portal.rmfactory.com.br
19 Introdução a Orientação a Objetos com Delphi

Use a diretiva implements para delegar à property da


classe a implementação dos métodos de uma interface.
type

IInterfaceA = interface
procedure Sample;
end;

TMyClass = class(TInterfacedObject, IInterfaceA)


FMyInterface: IInterfaceA;
property MyInterface: IInterfaceA read
FMyInterface implements IInterfaceA;
end;

TConcrete = class(TInterfacedObject, IInterfaceA)


public
procedure Sample;
end;

procedure TForm1.Button1Click(Sender: TObject);


var
MyClass: TMyClass;
InterfaceA: IInterfaceA;
begin
MyClass := TMyClass.Create;
MyClass.FMyInterface := TConcrete.Create;
InterfaceA := MyClass;
InterfaceA.Sample;
end;

POLIMORFISMO

Polimorfismo é o principal recurso que justifica o uso de


herança no seu código. Polimorfismo “várias formas” é uma
técnica que permite o aumento da abstração na chamada a
métodos de um objeto. Através de uma cadeia de heranças,
métodos são herdados da classe progenitora, ocasionando

portal.rmfactory.com.br
20 Introdução a Orientação a Objetos com Delphi

que todas as classes possuam o mesmo método, mas possuam


efeitos diferenciados.
TAnimal
procedure Walk;
end;

THuman = class(TAnimal) //herdará o método “Walk”


end;

TDog = class(TAnimal) //herdará o método “Walk”


end;

O polimorfismo é caracterizado no código quando


usamos as diretivas “virtual ou dynamic” e “override” nos
membros da classe. Isto indica que o método sinalizado como
“virtual” ou “dynamic” é um membro que pertence a uma
cadeia polimórfica, ou seja, as classes que herdarem métodos
com estas diretivas podem adicionar novas funcionalidades a
eles.
TAnimal
procedure Walk; virtual;
end;

THuman = class(TAnimal)
procedure Walk; override;
end;

TDog = class(TAnimal)
procedure Walk; override;
end;

Uma vez criada esta “cadeia polimórfica” para o método


“Walk” ganhamos uma maior flexibilidade ao codificar nossas
rotinas, uma vez que podemos “abstrair” o verdadeiro método
a ser invocado.

portal.rmfactory.com.br
21 Introdução a Orientação a Objetos com Delphi

procedure DoWalk(Animal: Tanimal);


begin
Animal.Walk;
end;

DoWalk(Tdog.Create);

Com isto, em tempo de execução, o Delphi irá decidir


qual método irá invocar, este recurso é chamado de ligação
tardia ou “late binding”, pois em tempo de desenvolvimento
não é possível se determinar qual instância será passada no
método DoWalk – pode ser qualquer classe que pertença a
hierarquia de Tanimal;

OVERRIDE E METHOD HIDES

A diretiva Override indica um método que é sobreposto


na classe onde ele é declarado. Seu uso é freqüente na
programação orientada a objetos e tem um papel agregador,
ou seja, adiciona funcionalidades a um método herdado, uma
vez que este tenha sido declarado como virtual ou dynamic. A
declaração de um método sobreposto deve seguir fielmente
a declaração do método na classe ancestral, fidelidade de
nome e lista de parâmetros. No entanto, há ocasiões em que
redeclaramos o método e não o sobrepomos. Isto ocasiona
um fato curioso ao compilar a aplicação:

[Warning] Unit2.pas(12): Method 'MethodName' hides


virtual method of base type 'TMyClass'

Este “warning” do compilador indica que o método


virtual “MethodName” declarado na classe ancestral TMyClass
foi ocultado. Isto é a indicação que houve uma “quebra da
cadeia polimórfica para o méthod MethodName”, ou seja, o
método não poderá ser invocado com “efeito polimórfico”, o
método não estará relacionado na VMT.

portal.rmfactory.com.br
22 Introdução a Orientação a Objetos com Delphi

Dica: Na sobreposição de metodos virtuais, na classe


corrente, posicionado em uma linha em branco, invoque o
“code completion” ctrl+space e todos os métodos passíveis de
sobreposição serão exibidos. Lembre-se a linha deverá estar
totalmente em branco para que funcione o atalho.
TMyClass = class
//invoque o code completion aqui!
end;

POLIMORFISMO TÁCITO. PENSANDO EM “CADEIA


POLIMÓRFICA”

A cadeia polimórfica é estabelecida quando um método


não estático é sobreposto seqüentemente ou não, nas diversas
classes pertencentes a uma hierarquia.
type

TFirstClass = class
procedure Sample; virtual;
end;

TSecondClass = class(TFirstClass)
procedure Sample; override;
end;

TThirdClass = class(TSecondClass)
procedure Sample; override;
end;

TFourthClass = class(TThirdClass)
procedure Sample; override;
end;

implementation

uses
Dialogs;

portal.rmfactory.com.br
23 Introdução a Orientação a Objetos com Delphi

procedure TSecondClass.Sample;
begin
ShowMessage('Second!');
end;

procedure TThirdClass.Sample;
begin
ShowMessage('Third!');
end;

procedure TFourthClass.Sample;
begin
ShowMessage('Fourth!');
end;

procedure TFirstClass.Sample;
begin
ShowMessage('First!');
end;

A palavra reservada “inherited” pode ser usada em


qualquer situação onde seja necessário identificar que o
método a ser invocado não é o da classe atual, mas sim, o da
classe ancestral. Mas neste exemplo não foi utilizado para não
confundir nosso foco central.

No código seguinte, é feita uma “quebra” intencional na


classe TFourthClass:
type

TFirstClass = class procedure


Sample;virtual;
end;

TSecondClass = class(TFirstClass)
procedure Sample; override;
end;

TThirdClass = class(TSecondClass)
procedure Sample; override;
end;

portal.rmfactory.com.br
24 Introdução a Orientação a Objetos com Delphi

TFourthClass = class(TThirdClass)
procedure Sample; virtual;
end;

O método “sample” na classe TfourthClass estabeleceu


um novo “teto” polimorfico. E a chamada teria um efeito
inusitado:
Var
FirstClass: TFirstClass;
begin
FirstClass := TFourthClass.Create;
FirstClass.Sample;
end;

Resultado: “Third!”

O que aconteceu é que o método “sample” da classe


TfirstClass não pertence mais a cadeia, pois foi declarado
como virtual e quebrou a seqüência hierárquica. Isto fez com
que em tempo de execução fosse “escolhido” para execução
o método da classe hierarquicamente acima. Se “sample”
fosse “override” o método de TfourthClass seria executado.

VIRTUAL OU DYNAMIC, EIS A QUESTÃO!

As diretivas Virtual e Dynamic são usadas para permitir


que o método sinalizado possa ser sobreposto. Um método
não estático (virtual ou dymaic) pode ser reescrito através da
diretiva “override”.

Então se ambos permitem a sobreposição, então qual a


real diferença entre eles? Na verdade, métodos virtuais ou
dinâmicos atendem ao mesmo problema, a da sobreposição
polimórfica, sendo que a diretiva “virtual” é indicada a
métodos que sofrem “override” com frequência, pois cria uma
entrada na VMT Virtual Method Table, a qual relaciona os
endereços de todos os métodos virtuais de um objeto. Esta

portal.rmfactory.com.br
25 Introdução a Orientação a Objetos com Delphi

abordagem é mais eficiente visto que o endereçamento da


VMT é criado em tempo de execução.

Ao criar novas especializações de uma classe, ela terá


sua própria VMT, relacionando todos os métodos virtuais
herdados e todos os que forem declarados na nova classe. Use
a diretiva “dynamic” para métodos que não são sobrepostos
com frequência, pois os mesmos são adicionados a Dynamic
Method Table, que é criada sob demanda.

SOBRECARGA DE MÉTODOS
Uma das regras na declaração de classes é que não
podem haver dois ou mais métodos com o mesmo nome,
ainda que com parâmetros diferentes.
type

TSample = class
procedure Calc(Value: integer);
function Calc(a,b: integer): integer; //erro
aqui!!
end;

implementation

uses
Dialogs, SysUtils;

procedure TSample.Calc(Value: integer);


begin
ShowMessage(IntToStr(Value));
end;

function TSample.Calc(a,b: integer): integer;


begin
result := a + b;
end;

Para permitir essa flexibilidade, é utilizada a diretiva


“overload” nos métodos envolvidos.

portal.rmfactory.com.br
26 Introdução a Orientação a Objetos com Delphi

type

TSample = class
procedure Calc(Value: integer); overload;
function Calc(a,b: integer):integer; overload;
end;

Ao utlizar a classe Tsample, os dois métodos estarão


disponíveis no code completion.
var
Sample: TSample;
return: integer;
begin
Sample := TSample.Create;
return := Sample.Calc(1, 2);
Sample.Calc(return);
end;

O compilador usará os critérios de número de


parâmetros, tipo dos parâmetros para determinar qual
método deverá ser invocado. No caso acima, o fator que
determinou o método a ser usado em cada situação foi o
número de parâmetros, uma vez que ambos requerem
parâmetros de tipos inteiros. O overload também pode ser
usado em casos de métodos herdados, para evitar seu
ocultamento.
TSample = class
procedure Calc(Value: integer); overload;
function Calc(a,b: integer): integer; overload;
procedure Test;
end;

TSample1 = class(TSample)
procedure Test(s: string);overload;
end;

portal.rmfactory.com.br
27 Introdução a Orientação a Objetos com Delphi

Com isto, para a classe Tsample1 agora tempos


disponível o método “Test” herdado da classe ancestral e
“Test(s: string)”, novo método sobrecarregado em Tsample1.

Na situação a seguir, é declarado dois métodos


sobrecarregados, ambos requerem parâmetros inteiros, porém
de tipos diferentes:
TCalculator = class
procedure Calc(si: ShortInt); overload;
procedure Calc(si: SmallInt); overload;
end;

Até aqui nenhum problema que possa nos impedir


compilar, mas o que faria o compilador caso eu invoque Calc
com o seguinte parâmetro:
var
Calculator: TCalculator;
begin
Calculator := TCalculator.Create;
Calculator.Calc(29);
end;

O compilador irá avaliar o tamanho (range) suportado


por cada tipo em ambos parâmetros.

Shortint -128..127 signed 8-bit


Smallint -32768..32767 signed 16-bit

Como o valor passado no parâmetro potencialmente


poderia ser suportado por ambos os tipos, será escolhido
aquele cujo tipo do parâmetro possui o menor intervalo.

MÉTODOS ABSTRATOS

Métodos declarados como abstratos usam a diretiva


“abstract”. Este tipo de método não possui implementação na

portal.rmfactory.com.br
28 Introdução a Orientação a Objetos com Delphi

classe onde foi declarado, deixando isto a cargo das classes


descendentes. O uso da diretiva “abstract” sempre virá
acompanhada de um “virtual” ou “dynamic”, para permitir
sobrescrever o método. Classes que especializam classes com
métodos abstratos não são obrigadas a implementá-los.
procedure Sample;virtual;abstract;

As classes descendentes podem sobrepor “override” o


método abstrato e implementá-lo. Ao invocar um método
abstrato que não tenha sido sobreposto a seguinte exceção
será erguida:
| Abstract error |

Métodos abstratos são usados em situações onde é


importante que todas as classes de uma cadeia hierárquica
tenha um determinado método, como por exemplo um
conjunto de classes que modelam o mundo animal, teríamos
a classe TMamifero com o método abstrato “Walk”, cuja
implementação estaria a cargo das classes descendentes.

TYPE CASTS
Type Cast é um mecanismo do Delphi Language que
permite a conversão pontual de um determinado tipo. Em
conjunto com polimorfismo, type casts tornam-se
indispensáveis na codificação de rotinas genéricas.

Type Casts são classificados em dois tipos: Value Type


Casts e Variable Type Casts. Observe neste exemplo a
aplicação de um Variable Type Cast:
TAnimal = class
Age: byte;
end;

TDog = class(TAnimal)
Pedigree: string;
end;

portal.rmfactory.com.br
29 Introdução a Orientação a Objetos com Delphi

TCat = class(TAnimal)
Name: string;
end;

var
Animal: TAnimal;
begin
Animal := TCat.Create;
TCat(Animal).Name := 'Lissi'; //type cast
end;

Observe que foi feita a conversão de uma variável do


tipo Tanimal para o tipo Tcat. Isso só foi possivel porque Tanimal
é ancestral comum a classe TCAt, em outras palavras, elas
pertencem a mesma cadeia hierárquica.

Value Type Casts são mais incomuns, não aparecem com


tanta freqüência. Veja este exemplo:
var
ascii: integer; begin
ascii := Integer('Z');

A variável ascii receberá o valor da tabela ASCII


correspondente a letra ‘Z’. Neste outro exemplo
var
obj: TObject;
P: Integer;
begin
Obj := TObject.Create(nil);
P := Integer(Obj); //pega o endereço de Obj
ShowMessage(TObject(P).ClassName);
end;

ENCAPSULAMENTO

portal.rmfactory.com.br
30 Introdução a Orientação a Objetos com Delphi

Todo objeto dever ser responsável por seus próprios


comportamentos, com isto garantir a integridade daquilo que
o faz funcionar de maneira regular. Encapsulamento é uma
técnica OO para ocultar determinados membros de um
objeto. Conhecido como “Data Hidding” o encapsulamento é
utilizado como mecanismo regulador de acesso aos dados de
um objetos. O encapsulamento torna as mudanças no
comportamento interno de um objeto transparentes para
outros objetos e auxilia na prevenção de problemas de efeitos
colaterais no código. Pegue o que varia no seu código e
encapsule!

Não é necessário se preocupar em saber “como” uma


tarefa é realizada, portanto que seja feita! Quando usamos o
método “Ligar” do objeto carro uma série de outros métodos
serão invocados internamente no objeto. Estes detalhes do
funcionamento não

No Delphi existem cláusulas que são utilizadas para


demarcar regiões de uma classe, que determinam qual o grau
de visibilidade de cada membro dentro destas regiões, são
elas Public, Protected, Private, Published, Strict Private, Strict
Protected.

Público - A propriedade ou método da classe pode ser


acessado por todas as demais entidades do sistema.

Privado - O acesso aos membros da classe só é permitido


aos métodos da própria classe.

Protegido - O acesso aos membros da classe só é


permitido a classes da mesma hierarquia.

Published - Regras de visibilidade idênticas ao public,


sendo que além disso; aparece no object inspector (no caso
de componentes do Delphi).

Um dos questionamentos que caberiam seria: O que


encapsular? Quando encapsular? Pra que encapsular?

portal.rmfactory.com.br
31 Introdução a Orientação a Objetos com Delphi

Evidentemente todas estas perguntas precisam e devem ser


respondidas e esclarecidas.

A linguagem Delphi fornece um recurso muito utilizado


quando trabalhamos com encapsulamento, as “Property’s”,
assim com os campos de uma classe, as propriedades criam
um mecanismo de leitura e escrita para um campo privado à
classe. Muito mais eficiente que a declaração simples de um
campo, propriedades permitem uma forma concreta de
controle do que pode ser escrito e lido de um determinado
campo. Quem nunca teve um erro em sua frente “Invalid
property value” quando entrou com um valor incompatível a
uma propriedade ainda que acidentalmente através do
object inspector.

Propriedades são declaradas geralmente nas seções


public ou published de uma classe e obedece a seguinte
semântica:
property NoDaPropriedade: Tipo read FNoDaPropriedade
write FnoDaPropriedade;

GET E SETS
Uma vez que as propriedades promovem uma forma de
encapsulamento e controle de leitura e escrita, podemos
substituir a leitura e escrita direto do campo por métodos Get
e Set.
Property Nome: string read GetNome write SetNome;

Os métodos GetNome e SetNome serão usados pela


property para as tarefas de leitura e escrita na variável
encapsulada. Isto nos permite criar um estágio de verificação
preliminar a escrita ou leitura do campo.

portal.rmfactory.com.br
32 Introdução a Orientação a Objetos com Delphi

O OPERADOR INDEX
Os métodos Get e Set são instrumentos eficientes no
controle da leitura e escrita por parte de uma propriedade,
mas pode ser tornar um elemento perturbador no que diz
respeito a legibilidade de uma classe, por isso, é possível
compartilhar um único par de métodos Get e Set entre diversas
propriedades indexadas. Para declarar esta funcionalidade
adicione a diretiva “index” seguido de um inteiro entre -
2147483647 e 2147483647 em todas as propriedades que irão
usar os métodos compartilhados:
Type
TAluno = class
private
FNome: string;
FEmail: string;
FTelefone: string;
function GetData(const Index: Integer): string;
procedure SetData(const Index: Integer; const
Value: string);
public
property Nome: string index 0 read GetData write
SetData;
property Email: string index 1 read GetData write
SetData;
property Telefone: string index 2 read GetData
write SetData;
end;

implementation

function TAluno.GetData(const Index: Integer):


string;
begin
case Index of
0: result := FNome;
1: result := FEmail;

portal.rmfactory.com.br
33 Introdução a Orientação a Objetos com Delphi

2: result := FTelefone;
end;
end;

procedure TAluno.SetData(const Index: Integer; const


Value: string);
begin
case Index of
0: FNome := Value;
1: FEmail:= Value;
2: FTelefone := Value;
end;
end;

Dica: Na declaração de propriedades, digite a penas até


o tipo, encerrando em seguida com ponto e virgula. Logo após
pressione “ctrl+shift+c” e o restante da estrutura da
propriedade será criada automaticamente.

PROPRIEDADES INDEXADAS
Propriedades podem ser declaradas de forma a permitir
a leitura seqüencial de uma estrutura ordinal como um array.
A declaração é bem simples, basta informa a lista de
parâmetros ao lado do nome da propriedade:

interface

uses
Classes;

type
TCliente = class
private
FTelsList: TStringList;
function GetTelefones(Index: integer): string;
procedure SetTelefones(Index: integer; const

portal.rmfactory.com.br
34 Introdução a Orientação a Objetos com Delphi

Value: string);
public
constructor Create; destructor Destroy; override;
property Telefones[Index: integer]: string read
GetTelefones write SetTelefones;
end;

implementation

uses
SysUtils;

constructor TCliente.Create;
begin
inherited;
FTelsList := TStringList.Create;
end;

destructor TCliente.Destroy;
begin
FreeAndNil(FTelsList);
inherited;
end;

function TCliente.GetTelefones(Index: integer):


string;
begin
result := FTelsList.Strings[Index];
end;

procedure TCliente.SetTelefones(Index: integer;


const Value: string);
begin
FTelsList.Strings[Index] := Value;
end;

Para Ter acesso a leitura e escrita na propriedade


Telefones informe o indice desejado:

portal.rmfactory.com.br
35 Introdução a Orientação a Objetos com Delphi

var
Cliente: TCliente;
begin
Cliente := TCliente.Create;
Cliente.Telefones[0] := '21 2223-1234';
end;

DEFAULT, NODEFAULT E STORED


Default, nodefault e stored são diretivas que determinam
se os dados de uma propriedade publicada podem ou não
serem gravados no .dfm de um formulário.

O especificador “default” tem efeito diferente


dependendo do tipo de propriedade onde foi declarado.
Quando usamos propriedades indexadas, é possível usar o
especificador “default”, de forma que seja possível suprimir a
identificação de uma propriedade no ato da sua utilização:
property Telefones[Index: integer]: string read
GetTelefones write SetTelefones; default;

var
Cliente: TCliente;
begin
Cliente := TCliente.Create;
Cliente[0] := '21 2223-1234';
end;

Em outra situação, o “default” pode ser usado para


determinar um valor inicial para uma propriedade, quando
seguido de sua declaração for declarado um valor compatível
ao tipo da propriedade:
property Idade: integer read FIdade write SetIdade
default 10;

portal.rmfactory.com.br
36 Introdução a Orientação a Objetos com Delphi

Alguns detalhes precisam ser observados quanto ao uso


do default nesta situação: É possível utilizá-lo somente em
propriedade cujo tipo é ordinal.

Use o especificador NoDefault somente em casos de


sobreposição (override) de propriedades, que será visto em
seguida. O especificador “stored” determina se o valor da
propriedade será efetivamente gravado (persistido) no .dfm
do formulário.
property Nome: string read FNome write SetNome
stored false;

ENCAPSULAMENTO E CLASSES AMIGAS


Classes ditas como “amigas” são classes que são
declaradas na mesma unidade (unit). É a característica do
compilador digamos que “não documentada”. Esta
característica da linguagem permite que membros privados e
protegidos de uma classe possa ser lido por outras classes na
mesma unit.

DATA ACCESS OBJETC - DAO

O
DAO – Data Access Object é um pattern J2EE
que objetiva criar uma camada abstrata e
encapsulada a qual o modelo pudesse utilizar
para persistir seus objetos, com isto, resolver a impedância que
existe entre os objetos e o banco de dados relacional. Ainda
que trabalhamos orientados a objetos, o banco de dados é
relacional, com isto, ainda há a necessidade de se trabalhar
com comandos SQL. O DAO gerenciará a conexão ao banco
de dados, fará o controle das gravações e obtenções de
dados.

Veja o problema segundo Martin Fowler:

portal.rmfactory.com.br
37 Introdução a Orientação a Objetos com Delphi

ESTRUTURA DAO

BUSINESSOBJECT
Representa os objetos do modelo, que requisitam acesso
à fonte de dados para obter e armazenar dados.

DATAACCESSOBJECT
É o objeto primário deste padrão, faz o acesso aos dados
transparente para uso dos BusinessObject’s.

portal.rmfactory.com.br
38 Introdução a Orientação a Objetos com Delphi

DATASOURCE
Representa uma implementação de uma fonte de
dados, seja ela um RDBMS, OODBMS, XML etc..

TRANSFEROBJECT
Representa um “Transfer Object” usado para conexões
remotas.
type

TDataSource = (dsInterbase, dsMSSQL, dsOracle);

TCliente = class
private
FEmail: string;
FNome: string;
FOID: integer;
procedure SetEmail(const Value: string);
procedure SetNome(const Value: string);
procedure SetOID(const Value: integer);
published
property OID: integer read FOID write SetOID;
property Nome: string read FNome write SetNome;
property Email: string read FEmail write SetEmail;
end;

IClienteDAO = interface
function Apply(Cliente: TCliente): boolean;
function Delete(Cliente: TCliente): boolean;
function List: TList;
function Find: TCliente;
end;

TClienteDAOMSSQL = class(TInterfacedObject,
IClienteDAO)
function Apply(Cliente: TCliente): boolean;
function Delete(Cliente: TCliente): boolean;
function List: TList;

portal.rmfactory.com.br
39 Introdução a Orientação a Objetos com Delphi

function Find: TCliente;


end;

TFactoryDAO = class abstract


function ClienteDAO: IClienteDAO;virtual;abstract;
class function GetDAOFactory(DataSource:
TDataSource): TFactoryDAO;
end;

TFactoryDAOMSSQL = class (TFactoryDAO)


class function CeateConnection: TSqlConnection;
function ClienteDAO: IClienteDAO; override;
end;

Implementation

procedure TCliente.SetEmail(const Value: string);


begin
FEmail := Value;
end;

procedure TCliente.SetNome(const Value: string);


begin
FNome := Value;
end;

procedure TCliente.SetOID(const Value: integer);


begin
FOID := Value;
end;

function TClienteDAOMSSQL.Apply(Cliente: TCliente):


boolean;
var
Conn: TSqlConnection;
strSQL: string;
begin
try
Conn := TFactoryDAOMSSQL.CeateConnection;
strSQL := 'Insert Into Cliente(Nome, Email)

portal.rmfactory.com.br
40 Introdução a Orientação a Objetos com Delphi

Values('+ QuotedStr(Cliente.Nome) + ','+


QuotedStr(Cliente.Email) + ')';
result := Conn.ExecuteDirect(strSQL) = 1;
finally
freeAndNil(Conn);
end;
end;

function TClienteDAOMSSQL.Delete(Cliente: TCliente):


boolean;
var
Conn: TSqlConnection;
strSQL: string;
begin
try
Conn := TFactoryDAOMSSQL.CeateConnection;
strSQL := 'Delete From Cliente Where ID=' +
IntToStr(Cliente.OID);
result := Conn.ExecuteDirect(strSQL) = 1;
finally
FreeAndNil(Conn);
end;
end;

function TClienteDAOMSSQL.Find: TCliente;


var
Conn: TSqlConnection;
Data: TSqlDataSet;
strSQL: string;
begin
try
Conn := TFactoryDAOMSSQL.CeateConnection;
strSQL := 'Select * From Cliente';
Data := TSQLDataSet.Create(nil);
Data.CommandText := strSQL;
Data.SQLConnection := Conn;
Data.Open;
if not Data.Eof then
with Data do

portal.rmfactory.com.br
41 Introdução a Orientação a Objetos com Delphi

begin
result := TCliente.Create;
result.Nome :=
Data.FieldByName('Nome').AsString;
result.Email:=
Data.FieldByName('Email').AsString;
end;
finally
freeAndNil(Conn);
freeAndNil(Data);
end;
end;

function TClienteDAOMSSQL.List: TList;


var
Conn: TSqlConnection;
Data: TSqlDataSet;
strSQL: string;
Cliente: TCliente;
begin
try
Conn := TFactoryDAOMSSQL.CeateConnection;
strSQL := 'Select * From Cliente';
Data := TSQLDataSet.Create(nil);
Data.CommandText := strSQL;
Data.SQLConnection := Conn;
Data.Open;
while not Data.Eof do
begin
Cliente := TCliente.Create;
with Data, Cliente do
begin
result := TList.Create;
Nome := Data.FieldByName('Nome').AsString;
Email := Data.FieldByName('Email').AsString;
Next;
end;
end;

portal.rmfactory.com.br
42 Introdução a Orientação a Objetos com Delphi

finally
freeAndNil(Conn);
freeAndNil(Data);
end;
end;

class function TFactoryDAO.GetDAOFactory(DataSource:


TDataSource): TFactoryDAO;
begin
case DataSource of
dsMSSQL: result := TFactoryDAOMSSQL.Create;
dsInterbase: {result := TFactoryDAOIBX.Create};
dsOracle: {result := TFactoryDAOOracle.Create};
end;
end;

class function TFactoryDAOMSSQL.CeateConnection:


TSqlConnection;
var
ASqlConn: TSqlConnection;
begin
ASqlConn := TSQLConnection.Create(nil);
ASqlConn.DriverName := 'MSSQL';
ASqlConn.GetDriverFunc := 'getSQLDriverMSSQL';
ASqlConn.LibraryName := 'dbexpmss.dll';
ASqlConn.VendorLib := 'oledb';
ASqlConn.Params.Values['HostName'] := 'localhost';
ASqlConn.Params.Values['Database'] := 'NorthWind';
ASqlConn.Params.Values['User_Name'] := 'sa';
ASqlConn.Params.Values['Password'] := '';
ASqlConn.LoginPrompt := false;
ASqlConn.Open; result := ASqlConn;
end;

function TFactoryDAOMSSQL.ClienteDAO: IClienteDAO;


begin
result := TClienteDAOMSSQL.Create;
end;

portal.rmfactory.com.br
43 Introdução a Orientação a Objetos com Delphi

var
FactoryDAO: TFactoryDAO;
ClienteDAO: IClienteDAO;
Cliente: TCliente;
begin
FactoryDAO :=
TFactoryDAOMSSQL.GetDaoFactory(dsMSSQL);
ClienteDAO := FactoryDAO.ClienteDAO;
Cliente := TCliente.Create;
Cliente.Nome := 'Rodrigo Mourão';
Cliente.Email :=
'rodrigomourao@rodrigomourao.com.br';
ClienteDAO.Apply(Cliente);
end;

CONCLUSÃO
Espero que estas poucas páginas tenham acrescentado
a você uma boa dose de conhecimento. Caso queira avançar
nos estudos da programação orientada a objetos com delphi,
não deixe de acessar meu curso gratuito de introdução a POO.

Clique aqui para acessar o curso gratuito

Não esqueça de se inscrever nas minhas redes sociais


para ficar por dentro de tudo que rola no portal RM Factory.
Cursos, eventos, Webinários, seminários, palestras e muitos
mais.

youtube.com/portalrmfactory

facebook.com/portalrmfactory

instagram.com/rodrigomouraocoach

portal.rmfactory.com.br

Potrebbero piacerti anche