0
\$\begingroup\$

I want to use the same variable for five different child classes. It is basically a boolean that is true when a player purchases an item(represented by a child class) and false when the player is yet to purchase that item. Then save the bool status.

Can someone tell me how to do just that?

Do I create five different bool variables each on their respective classes(the child classes), then access them individually when a player wants to buy the item? If I change the bool value of a parent class, it'll change it across all of it's child class.

\$\endgroup\$
  • \$\begingroup\$ "If I change the bool value of a parent class, it'll change it across all of it's child class." That sounds unusual. Can you show us the code you've used to attempt this so far? It sounds like you might be incorrectly using static variables, but seeing your code would help us diagnose the problem with more certainty. \$\endgroup\$ – DMGregory Sep 18 at 9:37
  • \$\begingroup\$ I've notice that you tagged this question both as C# and UnityScript. Are you sure you need an answer which explains how to do this in the old, deprecated UnityScript scripting language? If you only need a solution for writing Unity scripts in C#, please don't use that tag. \$\endgroup\$ – Philipp Sep 18 at 10:20
0
\$\begingroup\$

If you have a member variable in a base class you want to be visible to the subclasses but not to any unrelated classes, then declare that variable as protected.

Example:

public abstract class Item {

     protected bool isBought;

     public abstract void Buy(); 
}

/*-------------------------------*/

public class Sword : Item {

     public void Buy() {
          if (isBought) {
               Console.log("You can only use one sword, there is no point in buying another one");
          } else {
               Console.log("You purchased a sword!");
               isBought = true;
          }
     }
}

/*-------------------------------*/

public class Shield : Item {

     public void Buy() {
          if (isBought) {
               Console.log("Shields are heavy. You can't carry more than one.");
          } else {
               Console.log("You purchased a shield!");
               isBought = true;
          }
     }
}

Note that each instance of Item has a separate value for isBought. So the code above assumes that each of those child-classes only has one instance. If you have multiple instances of Sword, the isBought status is traced for each of those separately.

If your architecture assumes that there can be multiple instances of Sword, but you only ever want the player to own one of them, then it gets a bit more complicated. In that case I would implement a separate class Inventory which keeps track of what the player owns and which has some public methods which can be used to check if the player does or does not have an item matching some criteria.

\$\endgroup\$
  • \$\begingroup\$ Thanks! This helps. \$\endgroup\$ – MetaMax Sep 18 at 12:45
0
\$\begingroup\$

if you want to share a variable you should define it in parent or base class. if you define it protected or public, its accessible by all children children. its like you copy the variable in all of them.

basically in OOP low level components should depend on high level components with no inversion. so defining a variable in child class and access it in parent class breaks the rules(i didnt test it but it should be impossible)basically you instantiate concrete or low level classes.

if you think that way, your design is wrong. just read about (OOP, solid, Uncle Bob)

\$\endgroup\$
0
\$\begingroup\$

Encapsulation

Another option is to use encapsulation. The base class decides whether an item can be bought, depending on whether the item has an owner. We do assert here that an item can have at most 1 owner.

public abstract class Item
{
    public Person Owner { get; private set; }
    public bool IsBought => Owner != null;

    protected abstract bool OnBuy(Person buyer);

    public bool Buy(Person buyer)
    {
        if (IsBought)
        {
            Console.WriteLine("The item already has an owner");
            return false;
        }
        var wasBought = OnBuy(buyer);
        if (wasBought)
        {
            Owner = buyer;
        }
        return wasBought;
    }
}

Derived classes are not allowed to bypass the policy that an item which has already been bought can be bought again, but they can add additional checks whether the item could be bought. For instance, a child cannot buy a sword.

public class Sword : Item
{
    protected override bool OnBuy(Person buyer)
    {
        if (buyer.IsChild)
        {
            Console.WriteLine("A child cannot buy a sword");
            return false;
        }

        Console.WriteLine($"{buyer.Name} bought a sword");
        return true;
    }
}

The Person class used in this example:

public class Person
{
    public string Name;
    public bool IsChild;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.