Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Herança

class Serializador {

    constructor(contentType) {
        this.contentType = contentType;
    }
    ...

    filtrarObjeto(dados) {
        const novoObjeto = {};
        this.camposPublicos.forEach((campo) => {
            if (dados.hasOwnProperty(campo)) {
                novoObjeto[campo] = dados[campo];
            }
        });

        return novoObjeto;
    }
}


class SerializadorFornecedor extends Serializador {

    constructor(contentType, camposExtras) {
        super(contentType);
        this.contentType = contentType;
        this.camposPublicos = ['id', 'empresa', 'categoria'].concat(camposExtras || []);
    }
}

Por que tenho acesso a variável camposPublicos em Serializador sendo que esse atributo pertence somente a classe SerializadorFornecedor?

E por que não passamos o camposPublicos para o construtor de Serializador com super igual fizemos com contentType?

1 resposta
solução!

Em JavaScript você não precisa inicializar e nem declarar os atributos de uma classe pois é uma linguagem com tipagem dinâmica.

Aquele this.camposPublicos da classe Serializador será avaliado de acordo com o contexto (this) durante a execução do método filtrarObjeto. Como esse método só deve ser invocado pelos filhos de Serializador, o this. será uma referência ao objeto que é uma instância desse filho (por exemplo, uma instância da classe SerializadorFornecedor). Logo, this.camposPublicos em Serializador será o valor de this.camposPublicos inicializado em SerializadorFornecedor

Então, na prática, não existe isso de "y só pertence à classe x". É você quem estabelece um comportamento e interação entre os objetos. O instrutor aplicou, praticamente, o design pattern Strategy para criar os serializadores.

Se você criar uma instância de Serializador e invocar o filtrarObjeto, como this.camposPublicos nunca foi inicializado (ou seja, this.camposPublicos nesse contexto será undefined), o seguinte erro será lançado: TypeError: Cannot read property 'forEach' of undefined

Pode testar este codigo aí:

class Serializador {
    constructor(contentType) {
        this.contentType = contentType;
    }
    filtrarObjeto(dados) {
        const novoObjeto = {};
        this.camposPublicos.forEach((campo) => {
            if (dados.hasOwnProperty(campo)) {
                novoObjeto[campo] = dados[campo];
            }
        });
        return novoObjeto;
    }
}

const serializador = new Serializador()
serializador.filtrarObjeto({})

Sobre não passar o camposPublicos, faz sentido já que a classe Serializador não deveria conhecer o valor desse atributo pois o método que usa ele só será invocado por instâncias que conhecem (e inicializaram) ele em seu constructor. Como a lógica do método filtrarObjeto é genérica (dependendo apenas da definiçao de um camposPublicos), ele poderá ser reusada por todos os serializadores.

Note que em javascript há várias outras formas de obter esse mesmo comportamento que o instrutor quis ao organizar as classes assim.