Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Programação defensiva.

Observando o código abaixo fico me questionando

get data() {
    return new Date(this._data.getTime());
}

var n1 = new Negociacao (new Date(), 100, 5);
n1.data.setDate(23);

console.log(n1.data);

(1) Entendo que o this._data está protegido por meio da criação de um novo objeto.

(2) Eu estaria editando a cópia (novo Objeto) caso usasse o setDate().

(3) Mas se a afirmação (2) é verdadeira a data do return estaria incorreta considerando que o return é um novo objeto que recebe não mais this._data.getTime() como parâmetro mas, um novo argumento que foi inserido após o setDate().

Porque o return mostra a data certa se eu estaria modificando esta cópia (que é o que devia ser retornado)?

7 respostas

Fala ai Lucas, tudo bem? Vamos lá:

Porque o return mostra a data certa se eu estaria modificando esta cópia (que é o que devia ser retornado)?

Isso ocorre por causa da programação defensiva onde sempre retorna um novo objeto ao invés do atual da classe.

Dai o setDate está sendo chamado nesse novo objeto e não diretamente no _data.

Espero ter ajudado.

(1) RETORNA A PROPRIEDADE (não queremos isso)
get data() {
    return this._data;
}

var n1 = new Negociacao (new Date(), 100, 5);

n1.data.setDate(23); // Edito a propriedade do
 constructor (não queremos isso).

console.log(n1.data); // propriedade do constructor editada

(2) RETORNA A CÓPIA 
get data() {
    return new Date(this._data.getTime());  //Retorna a cópia
}

var n1 = new Negociacao (new Date(), 100, 5);
n1.data.setDate(23); // editando a CÓPIA

console.log(n1.data); // dando console **na cópia** e ela não foi alterada  (mas como ?????).

Você disse

Dai o setDate está sendo chamado nesse novo objeto e não diretamente no _data.

EXATOOOOOOOO!!!!!

Mas eu editei e dei return nesse novo objeto e ele não foi alterado. Eu to dando console.log() no _data, mas sua cópia então a data deveria ser modificada.

Eu realmente não entendo como alterei essa nova cópia e ao retorna-la não ouve alteração alguma.

Talvez eu não tenha entendido sobre escopo ou alguma caracteristica do new Date();

Isso ocorre por questões de referência de memória (algo mais complexo).

Vamos ver seu get novamente:

get data() {
    return new Date(this._data.getTime());
}

Toda vez que chamamos esse get, ou seja, quando fazemos .data ele vai criar um novo objeto Date, isso vai ter um novo endereço de memória, porém, os valores desse objeto serão os mesmos da _data com um novo endereço e espaço de memória.

Quando você faz o setDate:

n1.data.setDate(23)

Você está mudando a data esse novo objeto recém criado com um outro endereço de memória, o endereço de memória do _data está intacto.

Quando você faz o log (chamando o get novamente):

console.log(n1.data)

Ele vai criar um novo objeto Date com um novo endereço de memória e vai usar os valores do _data que não foram modificados.

Espero ter ajudado.

Deixa eu ver se entendi

(1) this._data é um objeto ----- um endereço

(2) n1.data é outro objeto -------- com outro endereço, mas com mesmo valor de (1)

(3) O n1.setDate() ----- cria outro objeto diferente de (1) e (2) ?

Então eu sempre estaria invocando (2) ?

Fala Lucas, vamos lá:

(1) this._data é um objeto ----- um endereço

Sim, this_data é uma variavel que referência um endereço de memória.

(2) n1.data é outro objeto -------- com outro endereço, mas com mesmo valor de (1)

Sim, o n1.data vai chamar o get que irá criar um novo objeto Date com um novo endereço de memória, porém, os valores serão os mesmos de this_data, isso porque passamos ela como parâmetro na criação do novo objeto: new Date(this._data.getTime()) (seria uma cópia).

(3) O n1.setDate() ----- cria outro objeto diferente de (1) e (2) ?

Não, aqui o setDate você altera os valores do segundo objeto (da cópia), isso porque tu chama n1.data.setDate, ou seja, o n1.data vai criar um novo Date (cópia) e o setDate será chamado para esse novo objeto.

Então eu sempre estaria invocando (2) ?

Quando utilizar o n1.data (get) sim, você está sempre manipulando e utilizando a cópia e não o objeto original.

Espero ter ajudado.

Desculpe a persistência Me confundi no que falei. Eu entendi que a propriedade do constructor está protegida. Eu não entendo o que ocorre com o return. Minha mente só pensa em dois caminhos. Modo 1

get data() {
    return new Date(this._data.getTime());  ----- Crie um novo objeto sempre que for invocado get data.
}

var n1 = new Negociacao (new Date(), 100, 5);

console.log(n1.data); ------ crie uma cópia (1) e a  mostre.  ---- data certa
n1.data.setDate(23); ------ crie outra cópia (2) e a edite. ---- editando uma cópia
console.log(n1.data); ------ crie outra cópia (3) e a mostre. ---- data certa

Se não for assim então seria dessa forma Modo 2

get data() {
    return new Date(this._data.getTime());  ----- Crie um novo objeto sempre que for invocado get data.
}

var n1 = new Negociacao (new Date(), 100, 5);

console.log(n1.data); ------ crie uma cópia (1). ------ data certa
n1.data.setDate(23); ------ edite a cópia (1). ------ editando a data
console.log(n1.data); ------ mostre a cópia (1) editada. ------ data editada
solução!

Fala Lucas, o funcionamento é conforme tu explicou no Modo 1, é exatamente daquele jeito que funcionam as coisas por baixo dos panos ali, você pegou a ideia.

Espero ter ajudado.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software