Na parte I demos uma passada geral no conceito de aspectos. Aqui veremos os mixins.
Mixins são classes incompletas que apenas atribuem determinado comportamento às classes herdeiras.
Vamos a um exemplo bem esdrúxulo, mas suficiente: um objeto que armazena notas de alunos em um arquivo.
Mixins são classes incompletas que apenas atribuem determinado comportamento às classes herdeiras.
Vamos a um exemplo bem esdrúxulo, mas suficiente: um objeto que armazena notas de alunos em um arquivo.
from cPickle import dumps, loads
import gdbm
__all__ = ['Banco', 'Notas']
class Banco(object):
def __init__(self, file=None):
if file is None:
file = 'notas.db'
if isinstance(file, basestring):
file = gdbm.open(file, 'c')
self.file = file
def close(self):
if self.file:
self.file.close()
self.file = None
class Notas(object):
def __init__(self, matricula, db):
self.matricula = matricula
if not isinstance(db, Banco):
raise TypeError(
'expected Banco instance, got {}'
.format(type(db).__name__)
)
self.db = db
try:
self.notas = loads(db[str(matricula)])
except KeyError:
self.notas = {}
def save(self):
db[str(self.matricula)] = dumps(self.notas)
@property
def primeiro_bimestre(self):
return self.notas.get('1bim')
@primeiro_bimestre.setter
def primeiro_bimestre(self, value):
self.notas['1bim'] = float(value)
@property
def segundo_bimestre(self):
return self.notas.get('2bim')
@segundo_bimestre.setter
def segundo_bimestre(self, value):
self.notas['2bim'] = float(value)
@property
def terceiro_bimestre(self):
return self.notas.get('3bim')
@terceiro_bimestre.setter
def terceiro_bimestre(self, value):
self.notas['3bim'] = float(value)
@property
def quarto_bimestre(self):
return self.notas.get('4bim')
@quarto_bimestre.setter
def quarto_bimestre(self, value):
self.notas['4bim'] = float(value)
@property
def recuperacao(self):
return self.notas.get('rec')
@recuperacao.setter
def recuperacao(self, value):
return self.notas['rec'] = float(value)
@property
def media(self):
soma = sum(
self.primeiro_bimestre or 0,
self.segundo_bimestre or 0,
self.terceiro_bimestre or 0,
self.quarto_bimestre or 0,
)
m = soma / 4.
rec = self.recuperacao
if rec is not None:
m = (m + rec) / 2.
return m
Repare que temos o mesmo problema apresentando na parte I: está tudo misturado em uma única classe!
Podemos separar as partes de gerência de banco e serialização em classes diferentes, dedicadas a seu próprio aspecto, chamadas mixins.
A classe de faz serialização pode ser apenas isso:
Podemos separar as partes de gerência de banco e serialização em classes diferentes, dedicadas a seu próprio aspecto, chamadas mixins.
A classe de faz serialização pode ser apenas isso:
class NotaSerializavelMixin(object):
def load(self):
s = self.retrieve()
self.notas = loads(s) if s else {}
def __str__(self):
return dumps(self.notas)
A gerência de banco vai para outro mixin:
class PersistenciaMixin(object):
def retrieve(self):
try:
return self.db[str(self.matricula)]
except KeyError:
return None
def save(self):
db[str(self.matricula)] = str(self)
Preferindo, é possível separar a gerência de notas em um mixin também:
class NotasMixin(object):
@property
def primeiro_bimestre(self):
return self.notas.get('1bim')
@primeiro_bimestre.setter
def primeiro_bimestre(self, value):
self.notas['1bim'] = float(value)
...
@property
def media(self):
soma = sum(
self.primeiro_bimestre or 0,
self.segundo_bimestre or 0,
self.terceiro_bimestre or 0,
self.quarto_bimestre or 0,
)
m = soma / 4.
rec = self.recuperacao
if rec is not None:
m = (m + rec) / 2.
return m
Ao final, a classe principal será apenas uma cola dos mixins:
class Notas(NotaSerializavelMixin, PersistenciaMixin, MotasMixin):
def __init__(self, matricula, db):
self.matricula = matricula
if not isinstance(db, Banco):
raise TypeError(
'expected Banco instance, got {}'
.format(type(db).__name__)
)
self.db = db
self.load()
A API da classe continua idêntica: recebe o número da matrícula e o banco na instanciação, propriedades para acessar as notas e método
save()
para salvá-las em arquivo, porém agora cada aspecto está isolado e encapsulado em seu próprio mixin.
[]’s
Cacilhας, La Batalema