1 Wednesday, February 1, 2012

Transcrição

1 Wednesday, February 1, 2012
Orientação a objetos
e frameworks
Wednesday, February 1, 2012
1
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
Wednesday, February 1, 2012
2
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)
Wednesday, February 1, 2012
3
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)
Wednesday, February 1, 2012
4
Smalltalk 1980
Wednesday, February 1, 2012
5
Squeak: Smalltalk livre
Wednesday, February 1, 2012
6
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
Wednesday, February 1, 2012
7
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.
Wednesday, February 1, 2012
8
Exemplo: um objeto dict
• Sobrecarga de operadores:
• [ ]:
• __getitem__
• __setitem__
>>> 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'}
Wednesday, February 1, 2012
9
Exemplo: um objeto dict
• Atributos de dados: __class__, __doc__
>>> 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)
Wednesday, February 1, 2012
10
Exemplo: um objeto dict
• Em Python, métodos também são atributos
>>> 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']
Wednesday, February 1, 2012
11
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)
Note:
Em Tkinter, atributos de
dados são acessados via [ ]:
__getitem__ e __setitem__
tictac()
relogio.mainloop()
Wednesday, February 1, 2012
12
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
Wednesday, February 1, 2012
13
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'>
Wednesday, February 1, 2012
14
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',)
Wednesday, February 1, 2012
15
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
Wednesday, February 1, 2012
16
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
File "<stdin>", line
TypeError: unsupported
>>> a + int(b)
19
>>> str(a) + b
'109'
>>> 77 * None
Traceback (most recent
File "<stdin>", line
TypeError: unsupported
>>>
Wednesday, February 1, 2012
call last):
1, in <module>
operand type(s) for +: 'int' and 'str'
call last):
1, in <module>
operand type(s) for *: 'int' and 'NoneType'
17
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'
Wednesday, February 1, 2012
18
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
Wednesday, February 1, 2012
19
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.
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.
Wednesday, February 1, 2012
JavaScript
(ECMAScript 5)
em Node.js 0.6
> 10 + '9'
'109'
> 10 + '9' * 1
19
> '10' + 9 * 1
'109'
> 0 == '0'
true
> 0 == ''
true
> '0' == ''
false
20
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
Wednesday, February 1, 2012
21
Tipagem em linguagens
Smalltalk
Python
Ruby
C (K&R)
C (ANSI)
Java
C#
JavaScript
PHP
Wednesday, February 1, 2012
dinâmica
dinâmica
dinâmica
estática
estática
estática
estática
dinâmica
dinâmica
forte
forte
forte
fraca
forte
forte
forte
fraca
fraca
}
combinação
perigosa:
bugs sorrateiros
22
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'
>>>
Wednesday, February 1, 2012
23
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
Wednesday, February 1, 2012
24
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'
Wednesday, February 1, 2012
25
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
Wednesday, February 1, 2012
26
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
Wednesday, February 1, 2012
27
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...
Wednesday, February 1, 2012
28
>>>
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
Wednesday, February 1, 2012
29
Exemplar de cão:
instância da classe Cao
>>> rex = Cao()
Wednesday, February 1, 2012
instanciação
30
instanciação
Classe Cao
class Mamifero(object):
"""lição de casa: implementar"""
>>> 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!
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
Wednesday, February 1, 2012
31
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)
•
atributos de dados na
classe funcionam
como valores default
para os atributos das
instâncas
•
__init__ é o
construtor, ou melhor,
o inicializador
modulo2.git/cao.py
Wednesday, February 1, 2012
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)
•
self é o 1º parâmetro
em todos os métodos
de instância
•
atributos da instância
só podem ser
acessados via self
modulo2.git/cao.py
Wednesday, February 1, 2012
33
Classe Cao
class Mamifero(object):
"""lição de casa: implementar"""
class Cao(Mamifero):
invocação
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
modulo2.git/cao.py
Wednesday, February 1, 2012
34
Mamifero: superclasse
UML
de Cao
class Mamifero(object):
"""lição de casa: implementar"""
diagrama de classe
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)
generalização
modulo2.git/cao.py
Wednesday, February 1, 2012
35
Subclasses de Cao
• Continuação
de cao.py
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)
Wednesday, February 1, 2012
Diz a lenda que o cão
São Bernardo leva um
pequeno barril de conhaque
para resgatar viajantes
perdidos na neve.
36
Subclasses
de Cao
>>> 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!
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)
Wednesday, February 1, 2012
37
Subclasses de Cao
• Continuação
de cao.py
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)
Wednesday, February 1, 2012
38
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
Wednesday, February 1, 2012
39
Uma pequena
parte da
hierarquia de
classes do
Tkinter
herança múltipla
mixin
he
ran
ça
mú
lt
ipl
Wednesday, February 1, 2012
a
40
Um pouco mais da hierarquia de classes do Tkinter
Wednesday, February 1, 2012
41
Hierarquia de classes dos objetos gráficos doTkinter
Wednesday, February 1, 2012
42
Herança
múltipla
• Refatoração
de cao.py
para cao2.py
• Reutilizar o
latido do
mastiff em
outros cães
grandes
mixin
heran
ça mú
ça
heran
ltipla
pla
múlti
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
Wednesday, February 1, 2012
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
Wednesday, February 1, 2012
44
As duas hierarquias
de um sistema OO
• Hierarquia de classes
• is-a: é um
• Hierarquia de objetos
• part-of: parte de
Object-oriented Analysis
and Design with Applications
2ed. - Grady Booch
Wednesday, February 1, 2012
45
As duas hierarquias
de um sistema OO
Object-oriented Analysis
and Design with Applications
3ed. - Booch et. al.
Wednesday, February 1, 2012
46
from Tkinter import Frame, Label, Button
Timer
• Exemplo
simples de
composição
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
Wednesday, February 1, 2012
47
from Tkinter import Frame, Label, Button
Timer
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
Wednesday, February 1, 2012
48
Composição
• Arranjo de partes de
um sistema
mostrador = Label()
• componentes,
sub-componentes...
bt_start = Button()
timer = Timer()
Wednesday, February 1, 2012
49
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
instan self.grid()
ciaçã
o
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)
row=1, sticky='we')
ão
ç self.bt_start.grid(column=0,
a
i
c
n
a
self.atualizar_mostrador()
inst
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)
instan
ciaçã
o
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
Wednesday, February 1, 2012
50
Composição em UML
composição
composição
Wednesday, February 1, 2012
51

Documentos relacionados