Programação Orientada aos Objectos Paulo Marques Departamento de Eng. Informática Universidade de Coimbra Set/2005 Uma Introdução Usando. - ppt carregar
PublicouMariana Motta Alterado mais de 6 anos atrás
Apresentação em tema: "Programação Orientada aos Objectos Paulo Marques Departamento de Eng. Informática Universidade de Coimbra Set/2005 Uma Introdução Usando."— Transcrição da apresentação:
1 Programação Orientada aos Objectos Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Set/2005 Uma Introdução Usando C++
2 2 Sobre o que é que vamos falar? Primeira parte... Linguagens de programação Conceitos de programação orientadas aos objectos Representação visual dos mesmos (UML) Como é que se exprimem em C++ Segunda parte... Network Simulator, uma aplicação OOP
3 3 » C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do, it blows away your whole leg. « Bjarne Stroustrup » If you think C++ is not overly complicated, just what is a protected abstract virtual base pure virtual private destructor and when was the last time you needed one? « Tom Cargill
4 4 Paradigmas de Programação Actualmente existem quatro paradigmas de linguagens de programação em uso comum: Imperativas (e.g. C, Pascal, Fortran) Funcionais (e.g. LISP, Scheme) Lógicas/Declarativas (e.g. Prolog) Orientadas-aos-Objectos (e.g. Java, C++, C#, Smalltalk) Hoje em dia a indústria é dominada pelos paradigmas Imperativo e Orientado-aos-Objectos
5 5 Linguagens Imperativas Para programar um computador diz-se que… PROGRAMA = ESTRUTURAS DADOS + ALGORITMOS No programa existem variáveis que representam os dados Existe um conjunto de instruções que sucessivamente, a cada instrução, altera o valor das variáveis, manipulando os dados Segue de forma bastante próxima o modelo básico de funcionamento do processador Exemplos: C, Pascal, Fortran
6 6 Programação Orientada aos Objectos Os grandes problema da programação imperativa, estruturada: Grande Acoplamento! Baixa Coesão! Estruturas de Dados f() g() h() f() m()f() j() l() f() k() p() Temos os dados, e o programa é constituído por milhares de funções que… -- Ou manipulam directamente esses dados -- Ou trocam imensos valores por parâmetro
7 7 Programação Orientada aos Objectos Em OOP (Object-Oriented Programming), as funções estão encapsuladas juntamente com os dados a que podem (e devem aceder) Dados f() g() h() Dados f() g() h() Dados l() m() q()
8 8 Programação Orientada aos Objectos A principal ideia das objectos é que: Apenas as funções relacionadas com os dados lhes podem aceder Reduzir o acoplamento e aumentar a coesão Isto é, permitir a construção de software em projectos de larga escala, de forma consistente e fácil de gerir Para além disso, é muito mais natural pensar em termos de objectos e suas relações do que em termos de dados e algoritmos Programação Imperativa Procedimental: PROGRAMA = DADOS + ALGORITMOS Programação Orientada aos Objectos PROGRAMA = OBJECTOS + RELAÇÕES
9 9 Programação OOP e o C++ Ole-Johan Dahl e Kristen Nygaard, Noruegueses, inventam a linguagem Simula-67, para simulação. A motivação foi que ao realizarem simulações sobre o mundo real, com centenas de entidades, tornava-se inviável especificar explicitamente todas as interacções possíveis. Introduziu o conceito de classe/encapsulamento, objecto e uma forma de herança Alan Kay, Americano, inventa a linguagem SmallTalk (circa 1972), considerada a primeira verdadeira linguagem OOP Tudo são objectos; Os objectos comunicam trocando mensagens. Fortemente associada ao GUI!...inventou o conceito de computador pessoal, GUI e Portátil, numa altura em que tal era... RADICAL! There is no reason anyone would want a computer in their home." (Ken Olsen, Digital Equipment Corp, 1977)
10 10 Programação OOP e o C++ Bell Labs, 1979, Bjarne Stroustrup queria ter classes e objectos na linguagem C Motivação: análise do Kernel do UNIX para possibilitar computação distribuída!... OOP facilitaria o processo Criou um pré-processador que compilava a sua linguagem C with Classes para C 1983, a linguagem é renomeada C++. 1985: primeira versão comercial Primeira linguagem com suporte OOP largamente utilizada na indústria Dominou os anos 90. Última versão do standard: 2003 Devido à complexidade da linguagem, praticamente nenhum compilador implementa o standard completamente...
11 11 Fundamentos da OOP Noção de Classe e Objecto Encapsulamento Herança Polimorfismo
12 12 Preliminares... (Temos de garantir os básicos!) // Importa biblioteca e passa a usar o espaço de nomes standard #include using namespace std; // Programa principal int main() { // Declara uma tabela de inteiros de tamanho variável vector myTable; // Adiciona-lhe 10 números for (unsigned i=0; i<10; i++) myTable.push_back(i); // Imprime o seu conteúdo for (unsigned i=0; i<myTable.size(); i++) cout << myTable[i] << endl; return 0; }
13 13 O resultado...
14 14 Noção de Classe e Objecto Uma classe representa um grupo (ou tipo) de coisas Exemplo: Pessoa, Automóvel É sempre um NOME Uma classe tem operações associadas: métodos Os métodos representam acções sobre uma entidade, logo são VERBOS Um objecto (ou instância) representa uma coisa em particular de um grupo. Exemplo: Paulo Marques, 43-23-XM Toda a programação OOP baseia-se em encontrar classes e relações entre classes!
15 15 Mais alguns exemplos Uma REDE possui NODOS. Cada NODO pode ser um COMPUTADOR ou um REPETIDOR Rede, Nodo, Computador e Repetidor são classes! Numa rede pode fazer-se um Broadcast Broadcast é um método! Um nodo pode enviar e receber PACOTEs Enviar e Receber são métodos! PACOTE é uma classe! Um LEITOR_DE_MP3 toca MUSICA! LEITOR e MUSICA são classes! Toca é um método!
16 16 Classe Pessoa class Pessoa { private: string _nome; int _idade; public: Pessoa(string nome, int idade); void imprime(); }; Pessoa.h #include "Pessoa.h int main() { Pessoa aluno("Carlos Manuel", 30); Pessoa professor("Guilherme To", 23); aluno.imprime(); professor.imprime(); return 0; } Basics.cpp
17 17 Classe Pessoa Pessoa aluno("Carlos Manuel", 30); Pessoa professor("Guilherme To", 23); aluno.imprime(); professor.imprime();
18 18 Classe Pessoa A existência de classes de coisas e as suas instâncias, permitem-me manipular e simular o mundo de forma abstracta! A noção de encapsulamento – os dados estarem escondidos – é fundamental! Pessoa aluno("Carlos Manuel", 30); Pessoa professor("Guilherme To", 23); aluno.imprime(); professor.imprime(); classe objectos (instâncias)
19 19 A implementação de Pessoa... Pessoa::Pessoa(string nome, int idade) { _nome = nome; _idade = idade; } void Pessoa::imprime() { cout << "[" << _nome << "/" << _idade << "]" << endl; } Pessoa.cpp
20 20 Herança É possível definir especializações de uma classe base. Chama-se a isso uma classe derivada A classe derivada contém tudo o que a base contém, mas com informação/métodos adicionais Um COMPUTADOR é um NODO de rede. Um REPETIDOR é um NODO de rede. Computador e Repetidor são tudo o que um Nodo de rede é, mas tendo funcionalidade específica! São classes derivadas de nodo! Um PATRÃO é uma PESSOA. Um EMPREGADO é uma PESSOA. Em qualquer caso, é possível encarar um Patrão ou um Empregado como sendo pessoas! Têm é mais funcionalidade. São classes derivadas!
21 21 Classes Patrão e Empregado class Empregado : public Pessoa { public: Empregado(string nome, int idade); void abreBalcao(); }; Empregado.h class Patrao : public Pessoa { private: string _codigoEmpresa; public: Patrao(string nome, int idade, string codigo); void abreCofre(); }; Patrao.h
22 22 Classes Patrão e Empregado (2) Empregado::Empregado(string nome, int idade) : Pessoa(nome, idade) { } void Empregado::abreBalcao() { cout << "Puff.. a abrir o balcao." << endl; } Empregado.cpp Patrao::Patrao(string nome, int idade, string codigo) : Pessoa(nome, idade), _codigoEmpresa(codigo) { } void Patrao::abreCofre() { cout << "Eheh, a abrir o cofre. Codigo: " << _codigoEmpresa << endl; } Patrao.cpp
23 23 E agora, a execução... Patrao patrao("Carlos Manuel", 30, "1234F"); Empregado empregado("Guilherme To", 23); patrao.imprime(); patrao.abreCofre(); empregado.imprime(); empregado.abreBalcao();
24 24 Interlúdio... Antes de podermos examinar o que é polimorfismo, temos de lidar com alguns detalhes...
25 25 Passagem por Valor, Referência e por Ponteiro Em C++, os parâmetros das funções podem ser passados por valor, por referência ou por ponteiro. Na passagem por valor, apenas uma cópia do valor é passado. Dentro da rotina, alterações na variável não afectam a variável original. Na passagem por referência, a variável que se encontra no parâmetro representa a variável original. Alterações na variável são reflectidas na variável original. Na passagem por ponteiro, é passado o endereço de memória onde se encontra o dado original. É possível guardar informação sobre onde se encontram esse dado.
26 26 Passagem por Valor (C++) #include using namespace std; void leNome(string nome) { nome = Critical; cout << nome << endl; } void main() { string nome = XSoft; leNome(nome); cout << nome << endl; } Ao chamar-se leNome(), o valor de nome é copiado para dentro da função. Não existe nenhuma relação entre a variável nome de leNome() e a variável nome do programa principal, excepto o seu valor inicial. Imprime… Critical XSoft
27 27 Passagem por Referência (C++) #include using namespace std; void leNome(string& nome) { nome = Critical; cout << nome << endl; } void main() { string nome = XSoft; leNome(nome); cout << nome << endl; } Ao chamar-se leNome(), nome em leNome() representa a variável original com a qual se chama o programa (note-se que não têm de ter o mesmo nome). Alterações feitas sobre variável na função reflectem-se na variável original! Imprime… Critical Critical
28 28 Ponteiros (C++) Em C++ moderno, a principal utilidade do uso de ponteiros é permitir guardar uma referência para um certo objecto. Notação... // Uma string string nome = Critical; // Um ponteiro para uma string... string* ptrNome = 0; // Uma atribuição... ptrNome = &nome; // Acesso à string original... cout << *ptrNome << endl; Critical nome (0x5490) 0 ptrNome (0x6000) 0x5490 ptrNome (0x6000)
29 29 Passagem de Ponteiros (C++) Em C++ moderno, a principal utilidade do uso de ponteiros é permitir guardar uma referência para um certo objecto, para ser utilizado mais tarde. string* ptrNome = 0; void guardaNome(string* nome) { ptrNome = nome; } void imprimeNome() { cout << *ptrNome << endl; } void main() { string nome = XSoft; guardaNome(&nome); imprimeNome(); nome = Critical; imprimeNome(); } Imprime… XSoft Critical
30 30 Polimorfismo Capacidade de objectos diferentes se comportarem de forma diferente quando recebem a mesma mensagem. Permite tratar da mesma forma todos os objectos. (uma mensagem é uma invocação de um método...) Um PATRÃO quando calcula o ordenado, calcula-o como sendo uma percentagem dos lucros da empresa. Um EMPREGADO, calcula-o como sendo um valor constante. Quando se chama imprime() em PATRÃO, deve dizer que é um patrão antes de dar os dados. Em empregado, deverá dizer que é um empregado. Patrao patrao(Sofia", 30, "1234F"); Empregado empregado(Carlos", 23); Pessoa* umaPessoa; umaPessoa = &patrao; umaPessoa->imprime(); umaPessoa = &empregado; umaPessoa->imprime(); Imprime… PATRAO[Sofia / 30] EMPREGADO[Carlos / 23] Comportamento diferente apesar de ser o mesmo código!
31 31 A classe Pessoa tem de ser modificada... A palavra chave virtual indica que o método foi pensado para ser modificado numa classe derivada. Quando se usa um ponteiro do tipo Pessoa*, o ambiente de execução tem de procurar saber qual é a verdadeira classe do objecto e chamar o método correcto class Pessoa { private: string _nome; int _idade; public: Pessoa(string nome, int idade); virtual void imprime(); }; Pessoa.h Sempre que se declara um método virtual, deve criar-se um destrutor virtual. Nós não iremos abordar esses tópicos neste crash course. Mas, no mundo real, se isto não for feito por levar a graves memory leaks!
32 32 Redefinição dos métodos imprime() void Empregado::imprime() { cout << EMPREGADO; Pessoa::Imprime(); } Empregado.cpp void Patrao::imprime() { cout << PATRAO; Pessoa::Imprime(); } Patrao.cpp class Empregado : public Pessoa { public: Empregado(string nome, int idade); void abreBalcao(); virtual void imprime(); }; Empregado.h class Patrao : public Pessoa { private: string _codigoEmpresa; public: Patrao(string nome, int idade, string codigo); void abreCofre(); virtual void imprime(); }; Patrao.h
33 33 A execução...
34 34 Herança, Polimorfismo e Redefinição Um aspecto muito importante do uso da herança é que todas as partes comuns, mesmo em termos de algoritmos, devem ser agrupadas na classe base. As classes abaixo são especializações Quando se redefine um método, pode sempre invocar-se a funcionalidade que já se encontrava disponível. E.g. Pessoa::imprime()
35 35 » Now this is not the end. It is not even the beginning of the end. But it is, perhaps, the end of the beginning « Winston Churchill Questions?
36 36 Moth found trapped between points at Relay # 70, Panel F, of the Mark II Aiken Relay Calculator while it was being tested at Harvard University, 9 September 1945. The operators affixed the moth to the computer log, with the entry: First actual case of bug being found. They put out the word that they had debugged the machine, thus introducing the term debugging a computer program. In 1988, the log, with the moth still taped by the entry, was in the Naval Surface Warfare Center Computer Museum at Dahlgren, Virginia. U.S. Naval Historical Center Photograph. http://www.history.navy.mil/index.html
37 Programação Orientada aos Objectos Paulo Marques Departamento de Eng. Informática Universidade de Coimbra pmarques@dei.uc.pt Set/2005 Network Simulator Um pequeno caso de estudo
38 38 Aviso! O exemplo que se segue é limitado e serve unicamente para ilustrar os pontos anteriormente explorados Em C++ real, existem algumas coisas que são feitas neste código que não devem ser feitas Eventuais problemas com memory leaks Performance... péssima Porquê é que o fazemos? Infelizmente, nesta short session, não é possível estudar a linguagem a fundo... » It has been discovered that C++ provides a remarkable facility for concealing the trival details of a program – such as where its bugs are « David Keppel
39 39 Simple Network A B C D E F
40 40 Simple Network (2) Temos NODOS Cada NODO pode ser um COMPUTADOR ou um REPETIDOR Os nodos enviam() e recebem() PACTOREs Os NODOS pertencem a uma SUBREDE Uma SUBREDE pode ter vários NODOS Um COMPUTADOR apenas pertence a uma SUBREDE Um REPETIDOR pode pertencer a várias SUBREDEs
41 41 Diagrama UML
42 42 Comportamento do Sistema COMPUTADOR: Se eu quero enviar um pacote faço broadcast para a minha sub-rede Se eu recebo um pacote caso seja para mim, imprimo-o caso contrário, descarto-o REPETIDOR: Se eu recebo um pacote caso seja para mim, imprimo-o caso contrário, envio-o para todas as redes a que estou ligado SUB-REDE Caso me peçam para fazer um broadcast de um pacote envio para todos os nodos excepto o de origem
43 43 Implementação – Programa Principal (Network.cpp) int main() { Computer computerA("Computer_A"); Computer computerB("Computer_B"); Computer computerC("Computer_C"); Computer computerD("Computer_D"); Computer computerE("Computer_E"); Computer computerF("Computer_F"); Bridge bridge("MyBridge"); Subnet subnet1; subnet1.addNode(computerA); subnet1.addNode(computerB); subnet1.addNode(computerC); subnet1.addNode(bridge); Subnet subnet2; subnet2.addNode(computerD); subnet2.addNode(computerE); subnet2.addNode(computerF); subnet2.addNode(bridge); Packet p1("Computer_A", "Computer_F", "Hello F!"); computerA.sendPacket(p1); } A B C D E F
44 44 O Resultado da Execução...
45 45 Como implementar uma relação 1 para 1? class Computer : public Node { private: Subnet* _subnet; public: void addToSubnet(Subnet& s); }; void Computer::addToSubnet(Subnet& net) { _subnet = &net; }
46 46 Como implementar uma relação 1 para N? class Bridge : public Node { private: vector _subnets; public: void addToSubnet(Subnet& s); }; void Bridge::addToSubnet(Subnet& net) { _subnets.push_back(&net); }
47 47 Interface – Node.h class Node { private: string _name; public: Node(string name); string getName(); virtual void sendPacket(Packet p) = 0; virtual void receivePacket(Packet p) = 0; virtual void addToSubnet(Subnet& net) = 0; };
48 48 Interface – Computer.h e Bridge.h class Computer : public Node { private: Subnet* _subnet; public: Computer(string name); virtual void addToSubnet(Subnet& net); virtual void sendPacket(Packet p); virtual void receivePacket(Packet p); }; class Bridge : public Node { private: vector _subnets; public: Bridge(string name); virtual void addToSubnet(Subnet& net); virtual void sendPacket(Packet p); virtual void receivePacket(Packet p); };
49 49 Interface – Subnet.h e Packet.h class Subnet { private: vector _nodes; public: Subnet(); void addNode(Node& node); void broadcast(Node& sender, Packet p); }; class Packet { private: string _from; string _to; string _msg; public: Packet(string from, string to, string msg); string getOrigin(); string getDestination(); string getMessage(); void print(); };
50 50 Implementação – Packet.cpp Packet::Packet(string from, string to, string msg) : _from(from), _to(to), _msg(msg) { } string Packet::getOrigin() { return _from; } string Packet::getDestination() { return _to; } string Packet::getMessage() { return _msg; } void Packet::print() { cout << "[FROM: " << _from << ", TO: " << _to << ", MSG: \"" << _msg << "\"]" << endl; }
51 51 Implementação – Node.cpp Node::Node(string name) : _name(name) { } string Node::getName() { return _name; }
52 52 Implementação – Computer.cpp Computer::Computer(string name) : Node(name), _subnet(0) { } void Computer::addToSubnet(Subnet& net) { _subnet = &net; } void Computer::sendPacket(Packet p) { _subnet->broadcast(*this, p); } void Computer::receivePacket(Packet p) { if (p.getDestination() == getName()) { cout << "[NODE " << getName() << "] RECEIVED MESSAGE: "; p.print(); } else { cout << "{Node " << getName() << "} Discarting packet: "; p.print(); }
53 53 Implementação – Bridge.cpp Bridge::Bridge(string name) : Node(name) { } void Bridge::addToSubnet(Subnet& net) { _subnets.push_back(&net); } void Bridge::sendPacket(Packet p) { for (unsigned i=0; i<_subnets.size(); i++) _subnets[i]->broadcast(*this, p); } void Bridge::receivePacket(Packet p) { if (p.getDestination() == getName()) { cout << "[BRIDGE " << getName() << "] RECEIVED MESSAGE: "; p.print(); } else { cout << "*Bridge " << getName() << "* Echoing packet: "; p.print(); sendPacket(p); }
54 54 Implementação – Subnet.cpp Subnet::Subnet() { } void Subnet::addNode(Node& node) { node.addToSubnet(*this); _nodes.push_back(&node); } void Subnet::broadcast(Node& sender, Packet p) { for (unsigned i=0; i<_nodes.size(); i++) if (&sender != _nodes[i]) _nodes[i]->receivePacket(p); }
55 55 Thats It! A B C D E F
56 56 Alguns exercícios... O que é que acontece se forem colocadas dois repetidores na rede? Como é que resolve o problema? Considere uma rede com fios em que existem encaminhadores (routers). Modele e implemente um sistema que permita enviar pacotes de qualquer endereço para qualquer endereço. Considere um jogo de cartas (Poker, Sueca,...). Modele o sistema e simule o decorrer de um jogo: Pessoa contra Pessoa Pessoa contra Computador Computador contra Computador
57 57 Para saber mais... C++ How to Program, 4th Edition by Harvey M. Deitel, Paul J. Deitel Prentice Hall, Aug. 2002 Uma introdução leve ao C++ C++ Primer, 4th Edition by Stanley B. Lippman et. al. Addison-Wesley Professional, Feb. 2005 Para aprender ao pormenor tudo o que há a saber sobre C++
58 58 Para saber mais... Object-Oriented Analysis and Design with Applications, 2nd Edition by Grady Booch Addison-Wesley Professional, Sep. 1993 Como fazer design orientado aos objectos! Notação desactualizada, mas uma referência; Muito educativo! The Unified Modeling Language User Guide, 2nd Ed. by Grady Booch, James Rumbaugh, Ivar Jacobson Addison-Wesley Professional, May 2005 Um tutorial extremamente claro sobre como fazer modelação usando a linguagem UML.
59 59 YOU ARE FREE TO USE THIS MATERIAL FOR YOUR PERSONAL LERNING OR REFERENCE, DISTRIBUTE IT AMONG COLLEGUES OR EVEN USE IT FOR TEACHING CLASSES. YOU MAY EVEN MODIFY IT, INCLUDING MORE INFORMATION OR CORRECTING STANDING ERRORS. THIS RIGHT IS GIVEN TO YOU AS LONG AS YOU KEEP THIS NOTICE AND GIVE PROPER CREDIT TO THE AUTHOR. YOU CANNOT REMOVE THE REFERENCES TO THE AUTHOR OR TO THE INFORMATICS ENGINEERING DEPARTMENT OF THE UNIVERSITY OF COIMBRA. (c) 2005 – Paulo Marques, pmarques@dei.uc.pt
Carregar ppt "Programação Orientada aos Objectos Paulo Marques Departamento de Eng. Informática Universidade de Coimbra Set/2005 Uma Introdução Usando."