1

I don't quite know how to phrase this so I'll just dive ahead and try to explain it as best as I can.

I don't quite know how to store class properties without using them, or something like that.

If we have a class of Message that contains a method called addMessage.

We want to use this method. inside of a class called Magic.

How exactly do we do this?

class Message {
    constructor(messageContainer) {
        this.message = messageContainer;
    }

    addMessage(msg) {
        this.message.innerText = msg;
    }
}

class Magic extends Message {
    constructor(magic) {
        super();
        this.magic = magic;
    }

    something() {
        this.addMessage('Some random message');
    }
}

We do:

const message = new Message(document.getElementById('message-container'))

in the code but never use message anywhere.

Instead we use Magic like so:

const magic = new Magic(something)

and then:

element.addEventListener('click', () => magic.something())

This does not work, it does seem logical to why it doesn't, its because message never gets used, but how could we make use of the addMessage method inside of Magic though?

I've tried a few things but nothing seems to work except for doing document.getElementById inside of the super(), but that seems to me like it defeats the point of using classes if I can't call it somehow in the code and have it keep the reference to the message container...

Any ideas?

Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
Nick09
  • 206
  • 2
  • 15

2 Answers2

2

The Magic constructor needs to take a messageContainer parameter to pass along to the Message constructor.

class Magic extends Message {
    constructor(messageContainer, magic) {
        super(messageContainer);
        this.magic = magic;
    }

    something() {
        this.addMessage('Some random message');
    }
}

const magic = new Magic(document.getElementById('message-container'), something)

If you have lots of parameters and don't want to have list them all when calling super(), use an object to hold them instead of using seperate parameters. Each class can use the object properties that pertain to it.

class Message {
  constructor(options) {
    this.message = options.messageContainer;
  }

  addMessage(msg) {
    this.message.innerText = msg;
  }
}

class Magic extends Message {
  constructor(options) {
    super(options);
    this.magic = options.magic;
  }

  something() {
    this.addMessage('Some random message');
  }
}

magic = new Magic({
  messageContainer: document.getElementById("message-container"),
  magic: something
});
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • But what if I have too many parameters coming in the *main* class? It was 9 parameters. What I'm trying to achieve is shorten them somehow, but if I still need to pass them on like that, its the same thing. What I was trying now and what helped was passing the initialized Message into Magic as a parameter, this helped because Messages gets 2 parameters where it is used and gets passed into Magic as 1 parameters, so it shortens it. But there has to be a better way, isn't there? – Nick09 Apr 09 '20 at 19:41
  • 1
    If you have lots of parameters, use an options object. Then each class can extract the parameters that it wants. – Barmar Apr 09 '20 at 19:44
  • You are a genius. Just amazing solution, so simple and yet so efficient. Thank you good sir! – Nick09 Apr 09 '20 at 19:48
1

Instead of inheritance, your use case is composed(Behavioral design patterns). Combining 2 objects to work together. here is basic sample to solve this.

class MessageContainer {
  constructor(messageContainer) {
    this.message = messageContainer;
  }
  addMessage(msg) {
    this.message.innerHTML = msg;
  }
}
class Magic {
  constructor(msgContainer) {
    this.container = msgContainer;
  }
  something() {
    this.container.addMessage("Some random message"+ new Date().getTime());
  }
}
const container = new MessageContainer(
  document.getElementById("message-container")
);

const magic = new Magic(container);

document.addEventListener("click", () => {
  magic.something();
});
 <div style="height: 100px; color: red;">
        click here
        <br/>
        <span id="message-container"></span>
    </div>
xdeepakv
  • 7,835
  • 2
  • 22
  • 32
  • This is exactly what I did to solve this, it works but to be honest I didn't know if this was good practice, but I now understand that it is. Thank you very much for your contribution, I'm sorry I can't mark both as the correct answer because you both brought some very good points to this subject, I hope that we can both be glad about the fact that maybe other people will need this thread and will make use of your solution as well! – Nick09 Apr 09 '20 at 19:51
  • you should not combine each other task. else it will be tightly couple. use delegate patter for you case it make sense to have this. Inheritance is when u want to get parent property. So inheritance is not good here. – xdeepakv Apr 09 '20 at 19:55
  • yes I completely agree, after a few solid hours of pushing to use this :D thank you very much for the insight xdeepakv! – Nick09 Apr 09 '20 at 19:56