• Nenhum resultado encontrado

Orientação a objetos e frameworks

N/A
N/A
Protected

Academic year: 2021

Share "Orientação a objetos e frameworks"

Copied!
51
0
0

Texto

(1)

Orientação a objetos e frameworks

(2)

Objetivo deste módulo

Apresentar conceitos fundamentais de:

orientação a objetos

organização de programas em vários módulos

Explicar conceitos a partir do nível básico para:

programadores que nunca usaram OO

programadores que já usaram OO em outras linguagens

(3)

Orientação a objetos:

a origem

Linguagem Simula 1967

Noruega: Ole-Johan Dahl e Kristen Nygaard

objetos, classes, sub-classes

métodos virtuais (funções associadas a objetos específicos em tempo de execução)

(4)

Orientação a objetos:

evolução

Smalltalk 1980

EUA, Xerox PARC (Palo Alto Research Center):

Alan Kay, Dan Ingalls, Adele Goldberg et. al.

terminologia:

“Object oriented programming”

“message passing”, “late binding” (a idéia por trás de métodos virtuais)

(5)

Smalltalk 1980

(6)

Squeak: Smalltalk livre

(7)

Conceito: “objeto”

Um componente de software que inclui dados (atributos) e comportamentos (métodos)

Em geral, os atributos são

manipulados pelos métodos do próprio objeto (encapsulamento)

Figuras: bycicle (bicicleta), The Java Tutorial

http://docs.oracle.com/javase/tutorial/java/concepts/object.html

(8)

Exemplo: um objeto dict

>>> d = {'AM':'Manaus', 'PE':'Recife', 'PR': 'Curitiba'}

>>> d.keys()

['PR', 'AM', 'PE']

>>> d.get('PE') 'Recife'

>>> d.pop('PR') 'Curitiba'

>>> d

{'AM': 'Manaus', 'PE': 'Recife'}

>>> len(d) 2

>>> d.__len__() 2

Métodos: keys, get, pop, __len__ etc.

(9)

Exemplo: um objeto dict

>>> d

{'AM': 'Manaus', 'PE': 'Recife'}

>>> d['AM']

'Manaus'

>>> d.__getitem__('AM') 'Manaus'

>>> d['MG'] = 'Belo Horizonte'

>>> d.__setitem__('RJ', 'Rio de Janeiro')

>>> d

{'MG': 'Belo Horizonte', 'AM': 'Manaus', 'RJ': 'Rio de Janeiro', 'PE': 'Recife'}

Sobrecarga de operadores:

[ ]:

__getitem__

__setitem__

(10)

Exemplo: um objeto dict

>>> d.__class__

<type 'dict'>

>>> print d.__doc__

dict() -> new empty dictionary.

dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs.

dict(seq) -> new dictionary initialized as if via:

d = {}

for k, v in seq:

d[k] = v

dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)

Atributos de dados: __class__, __doc__

(11)

Exemplo: um objeto dict

>>> dir(d)

['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__',

'__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',

'__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

Em Python, métodos também são atributos

(12)

Exemplo:

um objeto Tkinter.Label

import Tkinter

from time import strftime

relogio = Tkinter.Label() relogio.pack()

relogio['font'] = 'Helvetica 120 bold' relogio['text'] = strftime('%H:%M:%S') def tictac():

    agora = strftime('%H:%M:%S')     if agora != relogio['text']:

        relogio['text'] = agora     relogio.after(100, tictac) tictac()

relogio.mainloop()

Note:

Em Tkinter, atributos de

dados são acessados via [ ]:

__getitem__ e __setitem__

(13)

Objetos em linguagens

Existem linguagens “baseadas em objetos” e linguagens “orientadas a objetos”

baseadas em objetos: permitem que o programador use os tipos de objetos

fornecidos, mas não permitem que ele crie seus próprios tipos de objetos

Ex. Visual Basic antes da era .net

(14)

Objetos em Python

Tudo é objeto: não existem “tipos primitivos”

desde Python 2.2, dezembro de 2001

>>> 5 + 3 8

>>> 5 .__add__(3) 8

>>> type(5)

<type 'int'>

(15)

Funções são objetos

>>> def fatorial(n):

... '''devolve n!'''

... return 1 if n < 2 else n * fatorial(n-1) ...

>>> fatorial(5) 120

>>> fat = fatorial

>>> fat

<function fatorial at 0x1004b5f50>

>>> fat(42)

1405006117752879898543142606244511569936384000000000L

>>> fatorial.__doc__

'devolve n!'

>>> fatorial.__name__

'fatorial'

>>> fatorial.__code__

<code object fatorial at 0x1004b84e0, file "<stdin>", line 1>

>>> fatorial.__code__.co_varnames ('n',)

(16)

Funções são objetos

>>> fatorial.__code__.co_code

'|\x00\x00d\x01\x00j\x00\x00o\x05\x00\x01d\x02\x00S\x01|\x00\x00t\x00\x00|

\x00\x00d\x02\x00\x18\x83\x01\x00\x14S'

>>> from dis import dis

>>> dis(fatorial.__code__.co_code)

0 LOAD_FAST 0 (0) 3 LOAD_CONST 1 (1) 6 COMPARE_OP 0 (<)

9 JUMP_IF_FALSE 5 (to 17) 12 POP_TOP

13 LOAD_CONST 2 (2) 16 RETURN_VALUE

>> 17 POP_TOP

18 LOAD_FAST 0 (0) 21 LOAD_GLOBAL 0 (0) 24 LOAD_FAST 0 (0) 27 LOAD_CONST 2 (2) 30 BINARY_SUBTRACT

31 CALL_FUNCTION 1 34 BINARY_MULTIPLY

35 RETURN_VALUE

>>>

Bytecode da função fatorial

(17)

Objetos têm tipo

Tipagem forte: normalmente, Python não faz conversão automática entre tipos

>>> a = 10

>>> b = '9'

>>> a + b

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

TypeError: unsupported operand type(s) for +: 'int' and 'str'

>>> a + int(b) 19

>>> str(a) + b '109'

>>> 77 * None

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'

>>>

(18)

Tipagem dinâmica:

variáveis não têm tipo

>>> def dobro(x):

... return x * 2 ...

>>> dobro(7) 14

>>> dobro(7.1) 14.2

>>> dobro('bom') 'bombom'

>>> dobro([10, 20, 30]) [10, 20, 30, 10, 20, 30]

>>> dobro(None)

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

File "<stdin>", line 2, in dobro

TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'

(19)

Duck typing

“Se voa como um pato, nada como um pato e grasna como um pato, é um pato.”

Tipagem dinâmica permite duck typing (tipagem pato) estilo de programação que evita verificar os tipos dos objetos, mas apenas seus métodos

No exemplo anterior, a função dobro funciona com qualquer objeto x que consiga fazer x * 2

(20)

Tipagem forte x fraca

Tipagem forte x fraca refere-se a

conversão automática de valores de tipos diferente.

Linguagens de tipagem fraca são muito liberais na mistura entre tipos, e isso é uma fonte de bugs.

> 0 == '0' true

> 0 == '' true

> '0' == '' false

Veja alguns resultados estranhos obtidos com JavaScript, que tem tipagem fraca.

Em Python as três expressões acima geram TypeError, e as três últimas resultam False.

Python tem tipagem forte.

> 10 + '9' '109'

> 10 + '9' * 1 19

> '10' + 9 * 1 '109'

JavaScript

(ECMAScript 5) em Node.js 0.6

(21)

Tipagem forte x fraca, dinâmica x estática

Tipagem forte x fraca refere-se a conversão automática de valores de tipos diferentes

Tipagem dinâmica x estática refere-se à declaração dos tipos das variáveis, parâmetros formais e

valores devolvidos pelas funções

Linguagens de tipagem estática exigem a

declaração dos tipos, ou usam inferência de tipos para garantir que uma variável será associada a

somente a valores de um tipo

(22)

Tipagem em linguagens

Smalltalk dinâmica forte Python dinâmica forte Ruby dinâmica forte C (K&R) estática fraca C (ANSI) estática forte

Java estática forte C# estática forte JavaScript dinâmica fraca

PHP dinâmica fraca } combinaçãoperigosa:bugs sorrateiros

(23)

Conversões automáticas

Python faz algumas (poucas) conversões automáticas entre tipos:

Promoção de int para float

Promoção de str para unicode

assume o encoding padrão: ASCII por default

>>> 6 * 7.0 42.0

>>> 'Spam, ' + u'eggs' u'Spam, eggs'

>>>

(24)

Funções para

inspecionar objetos

type(obj): devolve o tipo do objeto

o tipo é uma classe

dir(obj): devolve os nomes dos atributos do objeto

métodos e atributos de dados

devolve uma lista útil para uso interativo, mas não necessariamente completa

(25)

Objetos podem

receber novos atributos

Em geral, é possível atribuir valores a atributos não pré-definidos, em tempo de execução.

Exceções: tipos embutidos, tipos com __slots__

>>> fatorial

<function fatorial at 0x1004b5f50>

>>> fatorial._autor = 'Fulano de Tal'

>>> fatorial._autor 'Fulano de Tal'

>>> s = 'sapo'

>>> s.nome = 'Joca'

Traceback (most recent call last):

...

AttributeError: 'str' object has no attribute 'nome'

(26)

Acesso dinâmico a atributos

getattr(obj, nome_do_atributo): acessar

hasattr(obj, nome_do_atributo): testar

setattr(obj, nome_do_atributo, valor): criar ou alterar

delattr(obj, nome_do_atributo): remover

(27)

Acesso dinâmico

>>> dobro

<function dobro at 0x1004412a8>

>>> dobro.__doc__

'devolve duas vezes x'

>>> getattr(dobro, '__doc__') 'devolve duas vezes x'

>>> hasattr(dobro, 'peso') False

>>> setattr(dobro, '_inspecao', '2012-01-31')

>>> dobro._inspecao '2012-01-31'

>>> del dobro._inspecao

>>> hasattr(dobro, '_inspecao') False

(28)

Acesso dinâmico

>>> t = (1,)

>>> type(t)

<type 'tuple'>

>>> for nome_atr in dir(t):

... print nome_atr.ljust(16), getattr(t, nome_atr) ...

__add__ <method-wrapper '__add__' of tuple object at...

__class__ <type 'tuple'>

__contains__ <method-wrapper '__contains__' of tuple object at...

__delattr__ <method-wrapper '__delattr__' of tuple object at...

__doc__ tuple() -> empty tuple

tuple(iterable) -> tuple initialized from iterable's items

If the argument is a tuple, the return value is the same object.

__eq__ <method-wrapper '__eq__' of tuple object at...

__format__ <built-in method __format__ of tuple object at...

[...]

__len__ <method-wrapper '__len__' of tuple object at...

[...]

__str__ <method-wrapper '__str__' of tuple object at...

__subclasshook__ <built-in method __subclasshook__ of type object at...

count <built-in method count of tuple object at...

index <built-in method index of tuple object at...

(29)

Conceito: “classe”

Uma categoria, ou tipo, de objeto

Uma idéia abstrata, uma forma platônica

Exemplo: classe “Cão”:

Eu digo: “Ontem eu comprei um cão”

Você não sabe exatamente qual cão, mas sabe:

é um mamífero, quadrúpede, carnívoro

pode ser domesticado (normalmente)

cabe em um automóvel

(30)

Exemplar de cão:

instância da classe Cao

>>> rex = Cao() instanciação

(31)

Classe Cao

modulo2.git/cao.py

instanciação

class Mamifero(object):

    """lição de casa: implementar"""

class Cao(Mamifero):

    qt_patas = 4

    carnivoro = True     nervoso = False

    def __init__(self, nome):

        self.nome = nome

    def latir(self, vezes=1):

        # quando nervoso, late o dobro

        vezes = vezes + (self.nervoso * vezes)         print self.nome + ':' + ' Au!' * vezes     def __str__(self):

        return self.nome     def __repr__(self):

        return 'Cao({0!r})'.format(self.nome)

>>> rex = Cao('Rex')

>>> rex

Cao('Rex')

>>> print rex Rex

>>> rex.qt_patas 4

>>> rex.latir() Rex: Au!

>>> rex.latir(2) Rex: Au! Au!

>>> rex.nervoso = True

>>> rex.latir(3)

Rex: Au! Au! Au! Au! Au! Au!

(32)

Classe Cao em Python

class Mamifero(object):

    """lição de casa: implementar"""

class Cao(Mamifero):

    qt_patas = 4

    carnivoro = True     nervoso = False

    def __init__(self, nome):

        self.nome = nome

    def latir(self, vezes=1):

        # quando nervoso, late o dobro

        vezes = vezes + (self.nervoso * vezes)         print self.nome + ':' + ' Au!' * vezes     def __str__(self):

        return self.nome     def __repr__(self):

        return 'Cao({0!r})'.format(self.nome)

modulo2.git/cao.py

atributos de dados na classe funcionam

como valores default para os atributos das instâncas

__init__ é o

construtor, ou melhor, o inicializador

(33)

Classe Cao em Python

class Mamifero(object):

    """lição de casa: implementar"""

class Cao(Mamifero):

    qt_patas = 4

    carnivoro = True     nervoso = False

    def __init__(self, nome):

        self.nome = nome

    def latir(self, vezes=1):

        # quando nervoso, late o dobro

        vezes = vezes + (self.nervoso * vezes)         print self.nome + ':' + ' Au!' * vezes     def __str__(self):

        return self.nome     def __repr__(self):

        return 'Cao({0!r})'.format(self.nome)

modulo2.git/cao.py

self é o 1º parâmetro em todos os métodos de instância

atributos da instância só podem ser

acessados via self

(34)

Classe Cao

modulo2.git/cao.py

class Mamifero(object):

    """lição de casa: implementar"""

class Cao(Mamifero):

    qt_patas = 4

    carnivoro = True     nervoso = False

    def __init__(self, nome):

        self.nome = nome

    def latir(self, vezes=1):

        # quando nervoso, late o dobro

        vezes = vezes + (self.nervoso * vezes)         print self.nome + ':' + ' Au!' * vezes     def __str__(self):

        return self.nome     def __repr__(self):

        return 'Cao({0!r})'.format(self.nome)

>>> rex = Cao('Rex')

>>> rex

Cao('Rex')

>>> print rex Rex

>>> rex.qt_patas 4

>>> rex.latir() Rex: Au!

>>> rex.latir(2) Rex: Au! Au!

na invocação do

método, a instância é passada implicitamente na posição do self

invocação

(35)

Mamifero: superclasse

de Cao diagrama de classeUML

modulo2.git/cao.py

generalização

class Mamifero(object):

    """lição de casa: implementar"""

class Cao(Mamifero):

    qt_patas = 4

    carnivoro = True     nervoso = False

    def __init__(self, nome):

        self.nome = nome

    def latir(self, vezes=1):

        # quando nervoso, late o dobro

        vezes = vezes + (self.nervoso * vezes)         print self.nome + ':' + ' Au!' * vezes     def __str__(self):

        return self.nome     def __repr__(self):

        return 'Cao({0!r})'.format(self.nome)

(36)

Subclasses de Cao

class Pequines(Cao):

    nervoso = True     

class Mastiff(Cao):

    def latir(self, vezes=1):

        # o mastiff não muda seu latido quando nervoso         print self.nome + ':' + ' Wuff!' * vezes

        

class SaoBernardo(Cao):

    def __init__(self, nome):

        Cao.__init__(self, nome)         self.doses = 10

    def servir(self):

        if self.doses == 0:

      raise ValueError('Acabou o conhaque!')         self.doses -= 1

        msg = '{0} serve o conhaque (restam {1} doses)'         print msg.format(self.nome, self.doses)

Diz a lenda que o cão São Bernardo leva um

pequeno barril de conhaque para resgatar viajantes

perdidos na neve.

Continuação de cao.py

(37)

Subclasses de Cao

class Pequines(Cao):

    nervoso = True     

class Mastiff(Cao):

    def latir(self, vezes=1):

        # o mastiff não muda seu latido quando nervoso         print self.nome + ':' + ' Wuff!' * vezes

        

class SaoBernardo(Cao):

    def __init__(self, nome):

        Cao.__init__(self, nome)         self.doses = 10

    def servir(self):

        if self.doses == 0:

      raise ValueError('Acabou o conhaque!')         self.doses -= 1

        msg = '{0} serve o conhaque (restam {1} doses)'         print msg.format(self.nome, self.doses)

>>> sansao = SaoBernardo('Sansao')

>>> sansao.servir()

Sansao serve o conhaque (restam 9 doses)

>>> sansao.doses = 1

>>> sansao.servir()

Sansao serve o conhaque (restam 0 doses)

>>> sansao.servir()

Traceback (most recent call last):

...

ValueError: Acabou o conhaque!

(38)

Subclasses de Cao

class Pequines(Cao):

    nervoso = True     

class Mastiff(Cao):

    def latir(self, vezes=1):

        # o mastiff não muda seu latido quando nervoso         print self.nome + ':' + ' Wuff!' * vezes

        

class SaoBernardo(Cao):

    def __init__(self, nome):

        Cao.__init__(self, nome)         self.doses = 10

    def servir(self):

        if self.doses == 0:

      raise ValueError('Acabou o conhaque!')         self.doses -= 1

        msg = '{0} serve o conhaque (restam {1} doses)'         print msg.format(self.nome, self.doses)

Continuação de cao.py

(39)

Relógio com classe

import Tkinter

from time import strftime

class Relogio(Tkinter.Label):

    def __init__(self):

        Tkinter.Label.__init__(self)         self.pack()

        self['text'] = strftime('%H:%M:%S')         self['font'] = 'Helvetica 120 bold'         self.tictac()

        

    def tictac(self):

        agora = strftime('%H:%M:%S')         if agora != self['text']:

      self['text'] = agora

        self.after(100, self.tictac) rel = Relogio()

rel.mainloop()

modulo2.git/relogio_oo.py

(40)

Uma pequena parte da

hierarquia de classes do

Tkinter

herança

múltipla

herança múltipla

mixin

(41)

Um pouco mais da hierarquia de classes do Tkinter

(42)

Hierarquia de classes dos objetos gráficos doTkinter

(43)

Herança múltipla

class Cao(Mamifero):

    qt_patas = 4

    carnivoro = True     nervoso = False

    def __init__(self, nome):

        self.nome = nome

    def latir(self, vezes=1):

        # quando nervoso, late o dobro

        vezes = vezes + (self.nervoso * vezes)         print self.nome + ':' + ' Au!' * vezes     def __str__(self):

        return self.nome     def __repr__(self):

        return 'Cao({0!r})'.format(self.nome)       

class Grande(object):

    """ Mixin: muda o latido"""

    def latir(self, vezes=1):

        # faz de conta que cães grandes não mudam         # seu latido quando nervosos

        print self.nome + ':' + ' Wuff!' * vezes     

class Mastiff(Grande, Cao):

    """ O mastiff é o maior cão que existe """

class SaoBernardo(Grande, Cao):

    def __init__(self, nome):

        Cao.__init__(self, nome)         self.doses = 10

    def servir(self):

        if self.doses == 0:

      raise ValueError('Acabou o conhaque!')         self.doses -= 1

        msg = '{0} serve o conhaque (restam {1} doses)'         print msg.format(self.nome, self.doses)

modulo2.git/cao2.py

herança

múltipla

herança múltipla mixin

Refatoração de cao.py

para cao2.py

Reutilizar o latido do

mastiff em outros cães grandes

(44)

Herança múltipla

class Cao(Mamifero):

    qt_patas = 4

    carnivoro = True     nervoso = False

    def __init__(self, nome):

        self.nome = nome

    def latir(self, vezes=1):

        # quando nervoso, late o dobro

        vezes = vezes + (self.nervoso * vezes)         print self.nome + ':' + ' Au!' * vezes     def __str__(self):

        return self.nome     def __repr__(self):

        return 'Cao({0!r})'.format(self.nome)       

class Grande(object):

    """ Mixin: muda o latido"""

    def latir(self, vezes=1):

        # faz de conta que cães grandes não mudam         # seu latido quando nervosos

        print self.nome + ':' + ' Wuff!' * vezes     

class Mastiff(Grande, Cao):

    """ O mastiff é o maior cão que existe """

class SaoBernardo(Grande, Cao):

    def __init__(self, nome):

        Cao.__init__(self, nome)         self.doses = 10

    def servir(self):

        if self.doses == 0:

      raise ValueError('Acabou o conhaque!')         self.doses -= 1

        msg = '{0} serve o conhaque (restam {1} doses)'         print msg.format(self.nome, self.doses)

modulo2.git/cao2.py

(45)

As duas hierarquias de um sistema OO

Object-oriented Analysis

and Design with Applications 2ed. - Grady Booch

Hierarquia de classes

is-a: é um

Hierarquia de objetos

part-of: parte de

(46)

As duas hierarquias de um sistema OO

Object-oriented Analysis

and Design with Applications 3ed. - Booch et. al.

(47)

from Tkinter import Frame, Label, Button

class Timer(Frame):

    def __init__(self):

        Frame.__init__(self)

        self.inicio = self.agora = 15

        self.pendente = None # alarme pendente         self.grid()

        self.mostrador = Label(self, width=2, anchor='e',        font='Helvetica 120 bold',)         self.mostrador.grid(column=0, row=0, sticky='nswe')

        self.bt_start = Button(self, text='Start', command=self.start)         self.bt_start.grid(column=0, row=1, sticky='we')

        self.atualizar_mostrador()         

    def atualizar_mostrador(self):

        self.mostrador['text'] = str(self.agora)         

    def start(self):

        if self.pendente:

      self.after_cancel(self.pendente)         self.agora = self.inicio

        self.atualizar_mostrador()

        self.pendente = self.after(1000, self.tictac)

    def tictac(self):

        self.agora -= 1

        self.atualizar_mostrador()         if self.agora > 0:

      self.pendente = self.after(1000, self.tictac) timer = Timer()

timer.mainloop()

Timer

Exemplo

simples de composição

modulo2.git/timer.py

(48)

from Tkinter import Frame, Label, Button

class Timer(Frame):

    def __init__(self):

        Frame.__init__(self)

        self.inicio = self.agora = 15

        self.pendente = None # alarme pendente         self.grid()

        self.mostrador = Label(self, width=2, anchor='e',        font='Helvetica 120 bold',)         self.mostrador.grid(column=0, row=0, sticky='nswe')

        self.bt_start = Button(self, text='Start', command=self.start)         self.bt_start.grid(column=0, row=1, sticky='we')

        self.atualizar_mostrador()         

    def atualizar_mostrador(self):

        self.mostrador['text'] = str(self.agora)         

    def start(self):

        if self.pendente:

      self.after_cancel(self.pendente)         self.agora = self.inicio

        self.atualizar_mostrador()

        self.pendente = self.after(1000, self.tictac)

    def tictac(self):

        self.agora -= 1

        self.atualizar_mostrador()         if self.agora > 0:

      self.pendente = self.after(1000, self.tictac) timer = Timer()

timer.mainloop()

Timer

modulo2.git/timer.py

(49)

timer = Timer()

bt_start = Button()

Composição

Arranjo de partes de um sistema

componentes,

sub-componentes...

mostrador = Label()

(50)

from Tkinter import Frame, Label, Button

class Timer(Frame):

    def __init__(self):

        Frame.__init__(self)

        self.inicio = self.agora = 15

        self.pendente = None # alarme pendente         self.grid()

        self.mostrador = Label(self, width=2, anchor='e',        font='Helvetica 120 bold',)         self.mostrador.grid(column=0, row=0, sticky='nswe')

        self.bt_start = Button(self, text='Start', command=self.start)         self.bt_start.grid(column=0, row=1, sticky='we')

        self.atualizar_mostrador()         

    def atualizar_mostrador(self):

        self.mostrador['text'] = str(self.agora)         

    def start(self):

        if self.pendente:

      self.after_cancel(self.pendente)         self.agora = self.inicio

        self.atualizar_mostrador()

        self.pendente = self.after(1000, self.tictac)

    def tictac(self):

        self.agora -= 1

        self.atualizar_mostrador()         if self.agora > 0:

      self.pendente = self.after(1000, self.tictac) timer = Timer()

timer.mainloop()

modulo2.git/timer.py

instanciação

instanciação

instanciação

(51)

Composição em UML

composição composição

Referências

Documentos relacionados

Tampa da unidade da chave Caixa superior de montagem Chave Allen de 2,5 mm Suporte de bateria (BM-E8020) Caixa inferior de montagem Unidade da chave Chave Allen de 5 mm

Por ter esse entendimento de como um meio de comunicação po- de propagar diversos conteúdos, entre eles a representação da ideologia, nos próximos tópicos tentaremos explanar um

O presente trabalho teve como objetivo avaliar a espécie Bambusa vulgaris (bambu-verde) como uma alternativa para a produção de carvão vegetal, bem como o

O projeto piStar-GODA é uma nova solução para estes problemas, permitindo a utilização do projeto piStar como frontend para a modelagem dos modelos orientados a objetivos,

(a) Escreva uma classe chamada de PlanoPrePago com 5 atributos: uma string contendo o nome do cliente, um inteiro que representa a quantidade de minutos máxima que o plano dá

Conceitos de orientação a objetos: tipos abstratos de dados, objetos, classes, métodos, visibilidade, escopo, encapsulamento, associações de classes, estruturas

n Se os atributos estão private e todo acesso agora será feito por get/set, sempre que precisar de pegar os valores dos atributos, mesmo dentro de métodos públicos da classe faça

● Quando não é definido a visibilidade, ela será pública ou seja, você pode modificar, herdar ou atribuir sem nenhum impedimento, não é necessário os métodos