loading...

re: Explain Calling And Setting Getters And Setters Like I'm Five VIEW POST

FULL DISCUSSION
 

UUUUUUUUGH. Okay. Sorry. Not at you, at JavaScript for this thing. (I'm not anti-JS, to be clear. I really enjoy it. But it's stuff like this that makes me crazy.) I tripped over this stuff last year on a side project, took Java last semester, hoped it would make more sense in JavaScript after getting some in-depth OOP under my belt and... nope. So, I think it's a pretty confusing thing, first off!

Okay, so. I'm going to assume, based on literally nothing but it makes explaining easier and easier to follow for anyone else reading, that you are new(er)(ish) to programming. (And full disclosure, I'm about to hit one-year myself, so I don't mean it as a bad thing at all!)

Getters and setters are common archetypal methods in many programming languages; specifically, in object-oriented programming languages like Java, C, all that jazz. Many have Very Strong Opinions on both sides of the matter as to whether or not they should exist or should be used--but regardless, they do exist, and they are used.

So, what the hell are they!

In most object-oriented languages, getters and setters refer to the properties of a given object. Getters are methods that return the value of that property; setters set it. JavaScript has many object-oriented features(1), and this taps into some of those.

The reason they're a thing and why they exist is a lot more clear in other languages. If you'll pardon the segway into Java--and I know you asked JavaScript, don't worry--

Let's say we want to make some superheroes. To do that, in Java, we need a class called Superhero.

class Superhero {
   private String capeColor;
   private int shoeSize;
   private String secretIdentity;
   private boolean isABird;
}

To make a superhero, we'd do this (and it looks really weird if you're not familiar with it, and even if you are, in my opinion(3), but):

// creates a new Superhero that we call batman
Superhero superman = new Superhero();

As a result, since Superman is a Superhero, and we said that Superheros have a capeColor and a shoeSize, we know Batman has those.

Here's the sticky wicket. In the first code snippet above, did you see the word private? That means that only Superman knows his own capeColor and his own shoeSize and most importantly, his own secretIdentity;

What this means is that in Java, the following would not run and would fail:

NosyReporter someRookie = new NosyReporter();

someRookie.yellReallyLoud("Hey, Superman is really " + superman.secretIdentity);

In JavaScript, you can do that--access the property directly through the dot operator.

Now, why on earth would you want that in a language? Because it makes things easier to maintain, it makes code safer and cleaner, and all that good stuff(2). When those properties are private, you can prevent other parts of a program you're writing from accidentally changing them and weird bugs from showing up. This protecting of properties from outside objects is called encapsulation and is hugely important in OOP.

Which is great!

And super annoying, because how often do we have variables that we never want any other part of the program to access?

And so, enter getters and setters. (See, I promised this had a point!)

Commonly in Java, C, etc and other languages with those features like PHP, you create getter and setter methods which allows "outsiders" to access those properties.

class Superhero {
   private String capeColor;
   private int shoeSize;
   private String secretIdentity;
   private boolean isABird;

   /* This method returns the  secretIdentity of the superhero */
   public String getSecretIdentity() {
        return secretIdentity;
   }

   /* This method assigns a secretIdentity to the Superhero */
   // "Public" means anyone can use it.
   //    (if it's bugging you, "void" means there is no return value :)) 
   public void setSecretIdentity(String someNewSecretIdentity) {
        // "this" refers to the object itself--Superman, etc.
        this.secretIdentity = someNewSecretIdentity;
   }
}

As a result, outside objects can now interact! So if our sneaky reporter got lucky, he could instead:

NosyReporter someRookie = new NosyReporter();

// haha, success! Take that, Superman!
someRookie.yellReallyLoud("Hey, Superman is really " + superman.getSecretIdentity());

So, in Java, and the other languages that I know of, "getter" and "setter" are common but not formal: ie, I could actually call getSecretIdentity() something as unrelated as totallyUselessMethodNameThatRevealsNothing() and it would totally still work--but would just be a really not helpful name.

.... I know that was long, and twisty, but. That's what's going on in the JavaScript. You have get and set doing those things because of the OOP idea of encapsulation and getters and setters, which is a useful idea--and sort of a hard sell in particular in JavaScript, where it's not enforced because you don't have to declare whether something is private, etc, so it becomes a sort of arbitrary weird layer unless you understand the original intended purpose.

In my opinion, I dislike MDN and others calling that using methods. I see their point, and certainly the fact that more is happening than setting or getting of a value complicates it... which is why I think they should be separately named clear methods. And that pattern is a thing I dislike about JavaScript -- and I'll be super honest, I've read that documentation many times before, including this evening again, and it still makes very little sense to me, and I've had a lot more experience since the first time I read it along with a hunk of object-oriented under my belt... and it still is really hard to follow.

Basically, get latest() is a means of having things happen when you want the value of latest, and enables that to happen--since you have to have a function or method for things to happen--while still letting you skip the parentheses because it's a single value representing a property.

I hope that helped and didn't make things worse, but for what it's worth, it's not clear at all in JavaScript, and I really like JavaScript!

(1) JavaScript has protoypal inheritance, not class-based. Which is far from the only difference, but a huge one.
(2) As with everything, there are differences of opinion and you can still have crazy OOP code, it's totally not perfect, but that's the intended purpose.
(3) I actually really strongly feel that stuff like Dog dog = new Dog() leads too quickly to semantic satiation and can lead to more bugs and always go for more specific or at least different variable names when I can, but anyways.

 

This is such a great reply. This deserves to be a post on it's own, it's very informative! (I just re-read that sentence and realized I comment like a spam-bot)

 

Quick, solve a captcha! ;)

And thank you :)

 

So first I wanted to say thanks for the detailed reply. I have to head off to work so am leaving a short response but when I get the chance to I will respond with more info. But I did want to quickly respond and say that I was able to figure out the answer. I think pretty much everything I describe below is a general overview of what you have already said but I figured I would also put what I found. Which will hopefully help others out.

Essentially what I figured out was that before get and set keywords were implemented. You used to have to define the get and set methods through the Object.define property method.
Which explains as to why we can call the get and set methods the way we do. Because they are actually just properties.I posted an example below that I got from the mdn docs.


var o = {}

Object.defineProperty(o, 'b', {
  // Using shorthand method names (ES2015 feature).
  // This is equivalent to:
  // get: function() { return bValue; },
  // set: function(newValue) { bValue = newValue; },
  get() { return bValue; },
  set(newValue) { bValue = newValue; },
  enumerable: true,
  configurable: true
});

o.b; // 38

Code of Conduct Report abuse