Aula 16 – Python – Orientação a Objetos 02

Programação orientada a objetos – continuação

Python - Orientação a Objeto

Python – Orientação a Objeto

Que fazer esse curso com certificação?

Acesse:

https://workover.com.br/python-codigo-fluente

Voltar para página principal do blog

Todas as aulas desse curso

Aula 15                 Aula 17

Antes de continuar, quero deixar meu link de afiliados na Hostinger: Hostinger

Dêem um joinha 👍 na página do Código Fluente no Facebook
Facebook

Esse é meu link de referidos na digitalocean .

Quem se cadastrar por ele, ganha $100.00 dólares de crédito na digitalocean:

Digital Ocean

Esse outro é da one.com:

One.com

Automatize tarefas do dia a dia com python:

Curso Python Bot

Curso Python Bot

Continuando de onde paramos na última aula.

A gente viu que podemos criar parâmetros novos em objetos em tempo de execução, o que em Java, por exemplo, não é possível.

Para criar a classe Point em java, seria mais ou menos isso:


public class Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
    public double getX() {
        return x;
    }
    public double getY() {
        return y;
    }
    @Override
    public String toString() {
        return ("(" + x + "," + y + ")"); 
    }

}

Se em tempo de execução você quiser inserir um parâmetro z a classe Point, não será possível, você será informado que o parâmetro não existe: Parameter z does not exist…

Voltando ao python

As classes podem ser definidas em qualquer lugar


def format_string(string, formatter=None):
    '''Formata uma string usando o objeto formatador, que deve ter um
     método format () que aceita uma string.'''
    class DefaultFormatter:
        '''Formata uma string em case title.'''
        def format(self, string):
            return str(string).title()
    if not formatter:
        formatter = DefaultFormatter()
    return formatter.format(string)

Nesse caso definimos a classe DefaultFormatter dentro do método format_string.

A função format_string aceita uma string e um objeto formatador opcional, e em seguida, aplica o formatador a string.

Se nenhum formatador for fornecido, ele usará o formatador default:

Case title() coloca todas as iniciais de palavras em maiúsculo.


hello_string = "Olá, tudo bem?"
print(" input: " + hello_string)
print("output: " + format_string(hello_string))

Saída:

 input: Olá, tudo bem?

output: Olá, Tudo Bem?

Quem pode acessar meus dados?

Nomes começados e terminados com 2 sublinhados__*__ )

Nomes que começam com 2 sublinhados são métodos ou variáveis privadas da classe.

Não crie variáveis, funções, métodos, classes, enfim, não crie nada que comece e termine com 2 sublinhados.

A documentação diz que isso causa problemas de compatibilidade, sem nenhum warning.

Nomes começados com 1 sublinhado: _*

Nomes que começam com 1 sublinhado, quando são criados dentro de um módulo (ou pacote), não são importados quando a gente usa o comando:
from modulo import *.

Quando criar um módulo que tenha alguma função, variável ou classe que você não queira que seja importada automaticamente, coloque o nome começando com 1 sublinhado. Exemplo: _funcao_interna().

Para deixar claro que o método ou variável são privados da classe, ou seja, não pode ser acessado fora dela, dê o nome ao método ou classe começando com 1 sublinhado.

Isso não os torna privados. É apenas uma convenção mesmo.

O encapsulamento existe no Python, mas ele não vai te proibir de tomar suas próprias decisões, por isso dizemos que é só uma convenção.

Nomes começados com 2 sublinhados: __*

Nomes começados com 2 sublinhados são métodos ou variáveis privados de uma classe.

Objetos externos não acessam uma propriedade ou método que comecem com sublinhado duplo __ 


class SecretString: # A not-at-all secure way to store a secret string.
    def __init__(self, plain_string, pass_phrase):
        self.__plain_string = plain_string
        self.__pass_phrase = pass_phrase
    def decrypt(self, pass_phrase): #Show string if the pass_phrase is correct.
        if pass_phrase == self.__pass_phrase:
            return self.__plain_string
        else:
            return ''

secret_string = SecretString("ACME: Top Secret", "antwerp")
print(secret_string.decrypt("antwerp"))
print(secret_string.__plain_text)

#Funciona !! … talvez não …
print(secret_string._SecretString__plain_string)

Dê um:

dir(secret_string)

Saída:

[‘_SecretString__pass_phrase’, ‘_SecretString__plain_string‘, ‘__class__’, ‘__delattr__’, ‘__dict__’, ‘__dir__’, ‘__doc__’, ‘__eq__’, ‘__format__’, ‘__ge__’, ‘__getattribute__’, ‘__gt__’, ‘__hash__’, ‘__init__’, ‘__init_subclass__’, ‘__le__’, ‘__lt__’, ‘__module__’, ‘__ne__’, ‘__new__’, ‘__reduce__’, ‘__reduce_ex__’, ‘__repr__’, ‘__setattr__’, ‘__sizeof__’, ‘__str__’, ‘__subclasshook__’, ‘__weakref__’, ‘decrypt’]

Quando criamos váriáveis e métodos com 2 sublinhados o python insere o nome da classe antes do nome da variável ou método que você criou.

Nome da classe: _SecretString

Nome da variável ou método: __plain_string

Herança básica

Nos permite criar relacionamento “é um(a)” entre duas ou mais classes, abstraindo detalhes comuns em superclasses e armazenando os específicos na subclasse.

Tecnicamente, todas as classes que criamos usam herança, todas as classes Python são subclasses de uma classe especial que se chama object.


class MySubClass(object):
    pass

Variáveis de classe


class Contact:
    all_contacts = []
    def __init__(self, name, email):
        self.name = name
        self.email = email
        Contact.all_contacts.append(self)

A lista all_contacts, como faz parte da definição da classe, é na verdade compartilhada por todas as instâncias dessa classe, mas, e se alguns dos nossos contatos também forem fornecedores?

Classe Supplier(fornecedor) age, isto é, se comporta como um contato também.


class Supplier(Contact):
    def order(self, order):
        print("Nós enviamos o pedido {} para o {}".format(order, self.name))

c = Contact("alguém qualquer", "somebody@example.net")
s = Supplier("fornecedor", "supplier@example.net")
print(c.name, c.email, s.name, s.email)
c.all_contacts
c.order("preciso de um alicate")
s.order("preciso de um alicate")

O contato não tem o atributo order, veja em laranja no código acima, isso vai gerar um erro de atributo.

O fornecedor pode fazer o que o contato pode fazer e mais tudo o que precisa como fornecedor.

Substituindo(Overriding) e Super


class Friend(Contact):
    def __init__(self, name, email, phone):
        self.name = name
        self.email = email
        self.phone = phone
class Friend(Contact):
    def __init__(self, name, email, phone):
        super().__init__(name, email)
        self.phone = phone

Herança múltipla

Como regra geral, se você acha que precisa de herança múltipla, provavelmente você está errado, mas, se você sabe que precisa mesmo, provavelmente está certo.


class MailSender:
    def send_mail(self, message):
        print("Enviando o email para: " + self.email)
        # Adicione a lógica de e-mail aqui
# Definindo uma nova classe que é um contato e um MailSender
class EmailableContact(Contact, MailSender):
    pass

e = EmailableContact("TotiCavalcanti", "toti@example.net")
Contact.all_contacts
e.send_mail("Olá, teste de e-mail aqui")

Polimorfismo

Diferentes comportamentos acontecem dependendo de qual subclasse está sendo usada, sem ter que saber explicitamente o que a subclasse realmente é:


class AudioFile:
    def __init__(self, filename):
        if not filename.endswith(self.ext):
            raise Exception("Formato inválido!")
        self.filename = filename
class MP3File(AudioFile):
    ext = "mp3"
    def play(self):
        print("Tocando {} como mp3".format(self.filename))
class WavFile(AudioFile):
    ext = "wav"
    def play(self):
        print("Tocando {} como wav".format(self.filename))
class OggFile(AudioFile):
    ext = "ogg"
    def play(self):
        print("Tocando {} como ogg".format(self.filename))

ogg = OggFile("myfile.ogg")
ogg.play()
mp3 = MP3File("myfile.mp3")
mp3.play()
not_an_mp3 = MP3File("myfile.ogg")

Duck Typing

Nos permite usar qualquer objeto que forneça o comportamento necessário sem forçá-lo a ser uma subclasse. O exemplo a seguir não estende o AudioFile, mas pode interagir com o Python usando exatamente a mesma interface:


class FlacFile:
    def __init__(self, filename):
        if not filename.endswith(".flac"):
            raise Exception("Formato inválido!")
        self.filename = filename
    def play(self):
        print("Tocando {} como flac".format(self.filename))

Valeu pessoal, nos vemos na próxima aula.  🖖

Voltar para página principal do blog

Todas as aulas desse curso

Aula 15                 Aula 17

Esse são meus link de afiliados na Hostinger: Hostinger

Curta a página do Código Fluente no Facebook
https://www.facebook.com/Codigofluente-338485370069035/

Meu link de referidos na digitalocean .

Quem se cadastrar por esse link, ganha $100.00 dólares de crédito na digitalocean:

Digital Ocean

E o da one.com:

One.com

Obrigado, até a próxima e bons estudos. 😉

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>