Use getters and setters -my understanding

Use getters and setters -my understanding
0

#1

OK , so I have spent a few days trying to work through this and some it makes a little sense to me but honestly not too much… so I will put my code in here. and explain what it is that I think is going on… I just need someone to untangle the mess please… So here we are :

function makeClass() {
  "use strict";
  /* Alter code below this line */
  class Thermostat {   **//  here I created ( or seemingly so) a class  - but it does not pass that particular test..**

    constructor (temperature){
      this.tempurature=temperature;     
     } // I have taken the new Themostat and now assigned a property temperature to it  (76)

    get Thermostat(temperature){
      return this.temperature =temperature;  // Here we are getting the temperature(76) which feels nearly redundant in its logical statement to me.. but I digress..** 

    set Thermostat(temperature){
      this.temperature=((temperature-32)*5/9 ; // conversion from Fahrenheit to Celsius  and assignment to  temperature
    }
  /* Alter code above this line */
  return Thermostat;
}
const Thermostat = makeClass();   **// Thermostat is assigned to the function  Make class  ( where the Thermostat class is created**  

const thermos = new Thermostat(76); // **setting in Fahrenheit scale  a New Thermostat object created with the property that is the number 76   - which I am guessing is  like saying**
**Thermostat { temperature: 76} ; ?**

let temp = thermos.temperature; // 24.44 in C      //  **Why do we have 2 different values being expressed here for  the same expression please ?** 
**Both are temp= thermos.temperature .. but  they are both either 24.44 AND 26 ?**  

thermos.temperature = 26;
temp = thermos.temperature; // 26 in C     

As a Side note… absolutely none of the tests pass with this code so I am sure I am probably way off base here. OK the student is ready to put down the pen… and listen…

Thank you in advance for your wisdom…


#2

I’ve edited your post for readability. When you enter a code block into the forum, precede it with a line of three backticks and follow it with a line of three backticks to make easier to read. See this post to find the backtick on your keyboard. The “preformatted text” tool in the editor (</>) will also add backticks around text.


#3

The link to the challenge is https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/es6/use-getters-and-setters-to-control-access-to-an-object


The actual challenge doesn’t quite make sense I feel, the explanation is confusing. But. You have a class, which accepts a temperature when you instantiate it.

The point of getters and setters is that you kinda hide the internal details, which is why this is wierd, it’s as if there is a big chunk of exaplanation about the challenge missing. And the language is wrong - it’s not a thermostat, and you aren’t just getting and setting a temperature, you’re getting a temperature in one specific scale, and setting it in another scale, it’s very confusing

So inside the class, whatever you call the internal property, it always represents fahrenheit. So you could do:

class Thermostat {
  constructor(fahrenheit) {
    this.fahrenheit = fahrenheit
  }
  
  get temperature() { // return a value in celsius }
  set temperature(fahrenheit) { // set a value }
}

When you get you want to return the temperature in celsius. When you set, that has to be fahrenheit. get takes no arguments. It means when you create the object, you can use this:

myThermostat.temperature

which calls get (note, no brackets), and

myThermostat.temperature(aNewTemperature)

which updates whatever the private interal property is called.

So the get and set are a matched pair, and they should both be called temperature


So, your code:

function makeClass() {
  "use strict";

  class Thermostat {
    constructor (temperature){
      this.tempurature=temperature;     
     }

Spelling error, tempurature. And this is irrelevant: the internal variable cannot be called temperature. It has to be called something else - _temperature will do, but that’s not really accurate, because it’s always fahrenheit internally, and “temperature” could mean fahrenheit, cesius or kelvin or whatever.

    get Thermostat(temperature){
      return this.temperature = temperature;

you are not getting the class, get Thermostat is wrong. get temperature()

No closing }, and get does not take an argument, it should just return this.temperature converted to Celsius - you are getting a value, not setting a value.

    set Thermostat(temperature){
      this.temperature=((temperature-32)*5/9 ;
    }

Like get, you are not setting the class, set Thermostat is wrong. And you are setting a temperature that should be in fahrenheit, so no conversion. set temperature(fahrenheit)

  /* Alter code above this line */
  return Thermostat;
}

Missing }: should close the class off, so should be before the /* Alter code above this line */


Just fyi, getters and setters are not terribly useful in JS because you can access and modify objects without any restrictions: they’re generally unecessary.


#4

Dan…

THank you for the reply ! I have been banging my head against the wall for nearly a week trying to get this into the gray matter…

I have interjected my notes inside your post…

Thank you !

class Thermostat {
  constructor(fahrenheit) {
    this.fahrenheit = fahrenheit
  }
  
  get temperature() { // return a value in celsius }
  set temperature(fahrenheit) { // set a value }
}

When you get you want to return the temperature in celsius. When you set , that has to be fahrenheit. get takes no arguments. It means when you create the object, you can use this:

** NOTE** So I understand that the original temp is in Fahrenheit - (76) but in the bottom of the challenge, there are listings for " thermos.tempurature giving a scale in Celsius… which seems to state 2 different values for the temperature ?? ( Note that the spelling error also occurs INSIDE the challenge ( possibly the originator also needed more coffee LOL ) But I digress…

So , first we are creating the object/class “Thermostat” - and in the constructior we create the key part of the key/value pair. the portion is there to adhere a name to the value side of the key/value pair - and work with that value…

Also, you noted that you want to return the value in C. so if the value is currently in F, then the calculations are made on the Get side of the Get/Set equation ?

It would seem that the first value 24.44 is correct I dont quite know where they came up with the 26 value .

myThermostat.temperature

**NOTE**  Is this where the thermos.temperature fits in ?    

which calls get (note, no brackets), and

myThermostat.temperature(aNewTemperature)

which updates whatever the private interal property is called.
[/quote]

Final Note - thank you for taking the time to explain this … I am sure I will eventually clear the fog… LOL


#5

Someone else was asking about the same challenge recently, and the first answer to that might be helpful: Understanding use getters and setters to Control Access to an Object

This challenge has…some issues. I said in the other thread that the more I look at it, the less it makes sense.

Yup, this the main point of getters/setters. They let you run {insert some logic} before you access (via get) or mutate (via set) a “hidden” variable on the object. So if you want to do some logic or validation, but you want that to be hidden from the user of your API, then you can use getters and setters.

I say “hidden” because JavaScript doesn’t (as things stand) have any concept of private variables. In a class-based OO language (Java, C# etc), you can have private variables in classes which a user of the class cannot manipulate directly. That isn’t the case in JS. Anyway, might be clearer with a [possibly] simpler example:

class Rectangle {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  get area() {
    return this.x * this.y;
  }
}

This kinda makes sense.

> const myRect = new Rectangle(4, 3)
> myRect.area
12

But you could just do

class Rectangle {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  area() {
    return this.x * this.y;
  }
}  

Which works kinda exactly the same (note I’m executing a function for area now):

> const myRect = new Rectangle(4, 3)
> myRect.area()
12

NOTE if someone else has an actual good example of getters and setters in JS, that would be great cos I’m at a loss as to an actual usecase that makes sense beyond “I don’t want to have a user of my class have to type some brackets” - they’re the only examples I can find and Google is not being helpful


#6

Dan,

I get the rectangle example… and I can plug in the values where Rectangle = Thermostat and the constructor (x,y) becomes the fahrenheit… and the Const my Rect = " const Thermos" in this example .

So …
get temperature() {

 return  (this.fahrenheit - 32 ) *5/9;

set temperature (fahrenheit) {
return this.fahrenheit ; ( ?)
}

This where all the math occurs on the getter side… and setter would take the value that is returned ?
This example is so very convoluted. In addition. gunhoo93 was correct in that the challenge " is bogus" for it lack of testing the understanding.

I am one of those people who go down the rabbit hole of the mind and I hate leaving things incomplete, or at least feeling like I missed something in the process that will bite me later LOL

SO here is where I am :

function makeClass() {
  "use strict";
  /* Alter code below this line */
  class Thermostat {
  constructor(fahrenheit) {
    this.fahrenheit = fahrenheit;
  }

  
     get temperature() {

 return  (this.fahrenheit - 32 ) *5/9;
set temperature (fahrenheit) {
return this.fahrenheit ;

}
     }
      
  /* Alter code above this line */
  return Thermostat;
}
const Thermostat = makeClass();
const thermos = new Thermostat(76); // setting in Fahrenheit scale
let temp = thermos.temperature; // 24.44 in C
thermos.temperature = 26;
temp = thermos.temperature; // 26 in C

#7

Setters shouldn’t return anything: all they do is mutate a variable. Only getters return a value.

Basically like

var example = {
  name: "Dan"
}

Get the name

> example.name
"Dan"

Set the name

> example.name = "Daniel"

Returns nothing.

Get the name

> example.name
"Daniel"

You could do (sorry, another contrived example):

const example = {
  _firstName: "Dan",
  _lastName: "Couper",
  get fullName() {
    return this._firstName + " " + this._lastName;
  },
  set fullName(name) {
    const [fname, lname] = name.split(" ");
    if (fname == "Harold") {
      console.log("I don't want my first name to be Harold");
    } else {
      console.log("New name set!");
      this._firstName = fname;
      this._lastName = lname;
    }
  },
};
> example.fullName
"Dan Couper"
> example.fullName = "Daniel Couper"
New name set!
> example.fullName
"Daniel Couper"
> example.fullName = "Harold Couper"
I don't want my first name to be Harold
> example.fullName
"Daniel Couper"

But there isn’t anything preventing _firstName or _lastName being updated directly, the setter doesn’t provide any protection. There are multiple other ways to break this code. (Note that JS does have a much more robust API for doing the above if it’s really needed, Proxy)

Just to emphasise, explicit getter and setter methods are not terribly useful in JS because you can mutate and access properties on objects freely, there are no restrictions. It is a maybe a bit hard to grok because there doesn’t seem to be a lot of point in them when you are learning. It kinda seems like a way to make an API cleaner but it just tends to make the code more complicated than it needs to be. In 5 years of writing JS professionally, working on fairly large JS codebases, I’ve used getters and setters precisely zero times, though that may just be me. I’ve deleted them a couple of times but that’s about it.

Edit: https://javascriptplayground.com/es5-getters-setters/


#8

I still keep coming back to this problem and I think I understand it more. The example that I found online was the following:

class Person {
      constructor (name, age) {
               this.name = name;
               this.age = age;
               this.nickname = "";
           }
    set nicknames(value){
                  this.nickname = value;
          }
    get nicknames(){
                  return `Your nickname is ${this.nickname}.`;
          }
    }
const alberto = new Person("Alberto", 25); //  here, I create a new class expression
alberto.nicknames = "Albi"; //here, I call the set function
alberto.nicknames; // Your nickname is Albi.

Reviewing this example, this is what I extrapolated.

function makeClass() {
  "use strict";
  
 class Thermostat {   
   constructor (Fahrenheit){ 
     this.temperature = Fahrenheit
   }
   set temperature(Fahrenheit){
     this.celsius = (5/9 * (Fahrenheit - 32));
   }
    get temperature(){
      return this.celsius;
    }
 }

  return Thermostat;
}
const Thermostat = makeClass(); // here, I'm assigning the variable Thermostat to my makeClass function so that when it 'returns Thermostat' it runs through the entire function
const thermos = new Thermostat(76); // here, I create a new class expression and set the class in Fahrenheit scale
let temp = thermos.temperature; // this assigns 'temp' to the temp finding method we've created for our class, possibly to simplify calling it in the console?
thermos.temperature = 100; // here, I'm calling the set function with an initial value of 100
temp = thermos.temperature; //'temp' is assigned to the newly called set function
console.log(temp); //here, I'm outputting temp, or 24.44 in Celsius