Class with grouped properties in deeper levels

Viewed 29

I'm trying to build a complex class where I want to group properties, making the instantiated object have multiple layers, instead of every property being at root level. So far, the only way I've found to do this is by making a class with the properties to group, and then in a "parent" class add a property of the class I built. The problem here though is that two properties not sharing the same class can't communicate with each other. There are ways around this, but I find them all very hacky and looking bad. One would be to create a hidden element, and store data in there that a property from another class can read. Another would be to create static properties, but then, unless you do some major work with that property, you can only have one object created from the parent class, as it'll be the same no matter the instantiation of the class.

Very basic example:

class A {
    constructor(prop1){
        this.property = prop1;
    }
}

class B {
    constructor(prop2){
        this.property = prop2;
    }
}

class C {
    constructor(prop1, prop2){
        this.PropertyA = new A(prop1);
        this.PropertyB = new B(prop2);
    }
}

let obj = new C(1, 1);

console.log(obj.PropertyA.property);

In this example, the property from class A can't get a value from property in class B.

So, my question is, is there another way of building the class C to keep the levels of hierarchy in the object?

I use the class structure because I like how it looks. It looks far more readable to me than the prototype structure, and I'm not building an object directly, as I would like to instantiate more of them. It feels like I have forgotten things I've looked at to try to do this, but I'm sure it'll come to me soon enough after I post this.

1 Answers

Sooo... I worked a bit on a static-solution, and basically made a private static property to hold a unique id per instantiated object, with the key-value pairs I want to be able to share between the different classes. This should only expose the methods to either set or get those values. The only requirement is that all the classes needs to be constructed with the object ID, so they can get the right value.

I understand that people will roll their eyes at my infantile tries to break the actual points of classes and such, but it works for me anyway in this specific circumstance anyway. I'm sure there a multitude of ways to update it to ensure it runs more smoothly, but I think it works for most cases at the moment.

The code made in example code:

"use strict";

class A {
    #id
    #testProp

    constructor(id){
        this.#id = id;
        this.#testProp = 10;
    }

    get TestProp(){ return this.#testProp + C.getSharedProp(this.#id, "BValue")};
    set TestProp(newValue) { this.#testProp = newValue; C.setSharedProp(this.#id, "AValue", this.#testProp) };
}

class B {
    #id
    #testProp

    constructor(id){
        this.#id = id;
        this.#testProp = 10;
    }

    get TestProp(){ return this.#testProp + C.getSharedProp(this.#id, "AValue")};
    set TestProp(newValue) { this.#testProp = newValue; C.setSharedProp(this.#id, "BValue", this.#testProp)  };

}

class C {
    #id
    constructor(){
        this.#id = Math.random().toString(36).substr(2, 9);
        this.PropertyA = new A(this.#id);
        this.PropertyB = new B(this.#id);
    }
    static #sharedProps = {};

    static getSharedProp(charId, valueName) {
        if(!charId){
            throw "Must supply character ID";
        }
        if(!valueName){
            throw "Must supply name of value to return";
        }
        if(!(charId in this.#sharedProps)){
            throw "Character ID not found";
        }
        if(!(valueName in this.#sharedProps[charId])){
            throw valueName + "-element not found";
        }
        return this.#sharedProps[charId][valueName];
    }

    static setSharedProp(charId, valueName, value) {
        if(!charId){
            throw "Must supply character ID";
        }
        if(!valueName){
            throw "Must supply name of value";
        }
        if(!(charId in this.#sharedProps)){
            this.#sharedProps[charId] = [];
        }
        if(!(valueName in this.#sharedProps[charId])){
            this.#sharedProps[charId][valueName] = -1;
        }
        if(!value){
            console.warn("Value not supplied of " + valueName + ". Not updating extant value");
        }else{
            this.#sharedProps[charId][valueName] = value;
        }
    }
}

let obj = new C();
obj.PropertyA.TestProp = 20;
obj.PropertyB.TestProp = 5;
console.log(obj.PropertyA.TestProp); //should be 25; 20 from its own class and 5 from foreign class-object
console.log(obj.PropertyB.TestProp); //should be 25; 5 from its own class and 20 from foreign class-object
Related