Pergunta

Eu sei que há um monte de perguntas semelhantes toneladas de grandes respostas a esta. Eu tentei olhar para os métodos de herança clássica, ou esses métodos de fechamento etc. De alguma forma, eu considero que eles são mais ou menos "hack" métodos para mim, como ele realmente não o que o javascript é projetado para fazer. (Ninguém Bem-vindo me corrija se eu estiver errado). OK, desde que ele funciona, eu satisfazer com o padrão de herança clássica como:

PARENTClass = function (basevar) { do something here; };
PARENTClass.prototype = { a: b, c: d}; // prototype is auto gen 

// Inheritance goes here
CHILDClass = function (childvar) { do something; };
CHILDClass.prototype = new PARENTClass(*1); // Actual inheritance to the prototype statement
// Instance
CHILDInstance = new CHILDClass(whatever);

Acima é de alguma forma, à minha compreensão da herança de JS. Mas um cenário que eu não tenho nenhuma idéia de como implementar, é que o que se eu quiser fazer alguma inicializar durante a criação do objeto (ou seja, dentro de construtor), e o novo objeto pode ser usado de imediato .... Minha ilustração de problema não pode ser muito claro, então deixe-me usar o seguinte C # Psuedo para explicar o que eu quero fazer:

class PARENT {
    public PARENT (basevar) { ... }
}
class CHILD : PARENT {
    public CHILD (basevar) : PARENT (basevar) // constructor of child, and call parent constructor during construct.
    { ... }
}

Por alguma razão (como o init. Elementos de UI), colocando-os no construtor parece ser a melhor maneira de fazer. Alguém tem idéia de como eu posso fazer isso.

PS: no * 1, eu não tenho idéia do que eu deveria colocar lá. PS2: A situação acima eu fiz encontrei a biblioteca jquery.inherit pode fazer, eu só me pergunto se não estiver usando biblioteca pode alcançá-lo. PS3: Ou o meu entendimento está errado. Desde javascript não se destina a OOP Mimick (é por isso que eu chamo-lhe cortar), qual é a lógica "correta" para implementar isso.

Foi útil?

Solução

Não é uma corte como tal; JavaScript é uma linguagem de protótipo, como definido pela Wikipedia como onde:

.. classes não estão presentes, e reutilização comportamento (conhecido como herança em linguagens baseadas em classes) é realizada através de um processo de clonagem de objectos existentes que servem como protótipos.

Como diz, classes não são usados ??em JavaScript; cada objeto que você cria é descendente da Object JavaScript; todos os objetos em JavaScript o objeto prototype, e todas as instâncias de objetos que você criar métodos 'herdar' e propriedades de objeto de protótipo de seu objeto. Dê uma olhada no MDC protótipo referência de objeto para mais informações.

A partir deste, quando você chamar a linha:

CHILDClass.prototype = new PARENTClass();

Isso permite que o objeto CHILDClass para adicionar métodos e propriedades ao seu objeto protótipo do objeto PARENTClass, o que cria um efeito semelhante à idéia de herança presentes em linguagens baseadas em classes. Desde o objeto prototype afeta cada instância criada desse objeto, isto permite que os métodos e propriedades do objeto pai para estar presente em cada instância do seu objeto filho.

Se você quiser chamar o construtor da sua classe pai no construtor de sua classe criança, você usa a função call JavaScript; isso permite que você chamar o construtor da classe pai no contexto do construtor da classe criança, portanto, definir as propriedades recém prototipados em sua classe filho para o que eles são definidos como na classe pai.

Você também não precisa colocar qualquer coisa onde você especificou o *1, uma vez que a linha é apenas usado para adicionar os métodos e propriedades para objeto de protótipo da classe infantil; No entanto, tenha em mente que ele chama o construtor da classe pai, por isso, se existem quaisquer argumentos que são fundamentais no funcionamento do construtor da classe pai, você deve verificar que estes estão presentes de modo a evitar erros de JavaScript.

Outras dicas

Você pode manualmente invocar o construtor pai no construtor da subclasse como esta:

CHILDClass = function (basevar) {
  PARENTClass.call(this, basevar);
  // do something;
};

O truque aqui é usar o método call, que lhe permite chamar um método no contexto de um objeto diferente. Consulte a documentação de call para mais detalhes.

JavaScript não tem suporte embutido para hierarquias de herança como extensão do tipo deve ser feito através de agregação, ou seja adicionando funcionalidade desejada diretamente para o próprio ou o seu protótipo objeto se a propriedade é para ser compartilhada entre instâncias.

No entanto, JS é poderoso o suficiente para fazer implementar outras formas de construção de objeto possível, incluindo herança clássica.

Dado um clone função - o que é suficiente para adicionar 'verdadeira' herança prototípica, e não abastardamento do JavaScript do mesmo - a sua exampe pode ser implementado como esta:

function ParentClass(baseVar) {
    // do stuff
}

// don't overwrite the prototype object if you want to keep `constructor`
// see http://joost.zeekat.nl/constructors-considered-mildly-confusing.html
ParentClass.prototype.a = 'b';
ParentClass.prototype.c = 'd';

function ChildClass(childVar) {
    // call the super constructor
    ParentClass.call(this, childVar);
}

// don't inherit from a ParentClass instance, but the actual prototype
ChildClass.prototype = clone(ParentClass.prototype);
ChildClass.prototype.e = 'f';

Também é possível adicionar um pouco de açúcar sintático para a herança baseada em classe - a minha própria implementação pode ser encontrada aqui .

O exemplo de cima, então, ler

var ParentClass = Class.extend({
    constructor: function(baseVar) {
        // do stuff
    },
    a: 'b',
    c: 'd'
});

var ChildClass = ParentClass.extend({
    e: 'f'
});

Eu tenho um invólucro OOP javascript leve que fornece 'Classe-like' herança, onde pode substituir métodos de base ou construtores de base chamada ou membros.

Você define suas classes como este:

//Define the 'Cat' class
function Cat(catType, firstName, lastName)
{
    //Call the 'Animal' constructor.
    Cat.$baseNew.call(this, firstName, lastName);

    this.catType = catType;
}
//Extend Animal, and Register the 'Cat' type.
Cat.extend(Animal, { type: 'Cat' }, {
    hello: function(text)
    {
        return "meaoow: " + text;
    },
    getFullName: function()
    {
        //Call the base 'Animal' getFullName method.
        return this.catType + ": " + Cat.$base.getFullName.call(this);
    }
})

//It has a built-in type system that lets you do stuff like:

var cat = new Cat("ginger", "kitty", "kat");
Cat.getType()                     // "Cat"
cat.getBaseTypesAndSelf()         // ["Cat","Animal","Class"]
cat.getType()                     // "Cat"
cat.isTypeOf(Animal.getType())    // "True"

var dynamicCat = Class.createNew("Cat", ["tab","fat","cat"])
dynamicCat.getBaseTypesAndSelf()  // ["Cat","Animal","Class"]
dynamicCat.getFullName()          // tab: fat cat

código fonte disponível em: Class. js

Eu também tenho mais detalhes no meu blog post sobre OOP em javascript

Apenas pensei em mencionar alguns dos problemas com o padrão clássico que você está indo para:

  1. Referência vars na classe super (es) estará disponível como essencialmente estática em todas as instâncias. Por exemplo, se você tem var arr = [1,2,3] no super, e fazer instance_1.arr.push (4) instance_2.arr.push (5) todos estes casos vai "ver" as alterações.
  2. Então você resolve 1. com solução de Ayman que Zákas chama de "Construtor Roubar", mas agora você chamar o construtor duas vezes: uma para o seu protótipo e uma vez para o construtor roubar. Solução - para o seu protótipo usar um ajudante como inheritPrototype (I mostrou toda a implementação deste neste post: inheritPrototype método FWIW, este essencialmente veio de uma combinação de página 181 do livro de Zákas e algum estudo Crockford.

  3. Sem privacidade (mas, novamente, você precisaria usar algo como o padrão de objeto durável para obter este e que pode não ser o que você quer)

  4. definição de objeto fica "pendurado":. Solution - colocar um if verificação para qualquer uma das funções do seu protótipo e, em seguida, definir o protótipo com um literal protótipo

eu correndo exemplos de tudo isso no github !!!

Tem sido um pouco como um grande desafio para mim verdadeiramente Grokar ambos: Zákas e Crockford livros sobre a criação do objeto e herança. Eu também precisava para tentar algumas diferentes quadros JavaScript TDD. Então, eu decidi criar um ensaio sobre ambos TDD Frameworks e JavaScript Object Creation & Herança. Tem a execução de código e os testes JSpec! Aqui está o link: * meu GitHub Open Source Essay / Book

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top