Herança, polimorfismo e encapsulamento são os três recursos mais distintos e importantes do OOP e, a partir deles, a herança tem uma estatística de alto uso nos dias de hoje. Estou aprendendo JavaScript e, aqui, todos dizem que tem uma herança prototípica, e as pessoas em todos os lugares dizem que é algo muito diferente da herança clássica.
No entanto, não consigo entender qual é a diferença entre eles do ponto de vista prático? Em outras palavras, quando você define uma classe base (protótipo) e extrai algumas subclasses dela, os dois têm acesso às funcionalidades da sua classe base e podem aumentar as funções nas classes derivadas. Se considerarmos o que eu disse ser o resultado pretendido da herança, por que deveríamos nos importar se estamos usando a versão prototípica ou clássica?
Para me esclarecer mais, não vejo diferença nos padrões de utilidade e uso da herança prototípica e clássica. Isso resulta em eu não ter interesse em saber por que eles são diferentes, pois ambos resultam na mesma coisa, OOAD. Quão praticamente (não teoricamente) a herança prototípica é diferente da herança clássica?
fonte
A herança clássica herda o comportamento, sem nenhum estado, da classe pai. Ele herda o comportamento no momento em que o objeto é instanciado.
A herança prototípica herda comportamento e estado do objeto pai. Ele herda o comportamento e o estado no momento em que o objeto é chamado. Quando o objeto pai é alterado no tempo de execução, o estado e o comportamento dos objetos filho são afetados.
A "vantagem" da herança prototípica é que você pode "corrigir" o estado e o comportamento depois que todos os seus objetos forem instanciados. Por exemplo, na estrutura Ext JS, é comum carregar "substituições" que corrigem os principais componentes da estrutura após a instanciação da estrutura.
fonte
class C(object): def m(self, x): return x*2
einstance = C()
então quando eu corroinstance.m(3)
eu recebo6
. Mas se eu mudarC
assimC.m = lambda s, x: x*x
e eu corroinstance.m(3)
, agora entendo9
. O mesmo acontece se eu criar umclass D(C)
e alterar um método, emC
qualquer instância deD
receber o método alterado também. Estou entendendo mal ou isso significa que o Python não tem herança clássica de acordo com sua definição?Primeiro: na maioria das vezes, você estará usando objetos, sem defini-los, e o uso de objetos é o mesmo nos dois paradigmas.
Segundo: a maioria dos ambientes prototípicos usa o mesmo tipo de divisão que os ambientes baseados em classe - dados mutáveis na instância, com métodos herdados. Portanto, há muito pouca diferença novamente. (Veja a minha resposta a esta pergunta de estouro de pilha , eo Papel Auto Organizador programas sem Classes . Olhe para citeseer para uma versão PDF .)
Terceiro: a natureza dinâmica do Javascript tem uma influência muito maior que o tipo de herança. O fato de poder adicionar um novo método a todas as instâncias de um tipo, atribuindo-o ao objeto base, é puro, mas posso fazer a mesma coisa no Ruby, reabrindo a classe.
Quarto: as diferenças práticas são pequenas, enquanto a questão prática de esquecer de usar
new
é muito maior - ou seja, é muito mais provável que você seja afetado pela falta de umnew
do que pela diferença entre o código prototípico e o código clássico .Tudo o que foi dito, a diferença prática entre herança prototípica e clássica é que seus métodos de coisas que mantêm (classes) são os mesmos que seus dados de coisas que mantêm (instâncias). Isso significa que você pode criar suas classes aos poucos, usando as mesmas ferramentas de manipulação de objetos que você usaria em qualquer instância. (De fato, é assim que todas as bibliotecas de emulação de classe fazem isso. Para uma abordagem não muito parecida com todas as outras, veja Traits.js ). Isso é principalmente interessante se você é metaprogramador.
fonte
A herança prototípica no JavaScript é diferente das classes das seguintes maneiras importantes:
Construtores são simplesmente funções que você pode chamar sem
new
:Não há variáveis ou métodos privados, na melhor das hipóteses você pode fazer isso:
No exemplo anterior, você não pode estender a classe significativamente se recorrer a variáveis e métodos privados falsos e, além disso, quaisquer métodos públicos que você declarou serão recriados toda vez que uma nova instância for criada.
fonte
color
,r
,x
,y
edrawCircle
que estão vinculados ao âmbito lexical deCircle
Circle.call()
como construtor? Parece que você está tentando descrever "objetos funcionais" (um equívoco ...)