John Bustos
John Bustos

Reputation: 19544

Static / Shared variable across certain instances of a class but not others

This may just be me showing my lack of knowledge / bad programming practice, but i'm curious to know if: a) This already exists b) If it doesn't exist, if it's bad programming practice to do so

But here's my question:

Suppose I have a class, let's call it "Computer" and it holds data of all the computers in a company. Now, it just so happens that this company has thousands of Dell computers and thousands of HPs and nothing else. (Again please stick with me here, this is just an example to illustrate my point)

Now, I could define my class as follows:

Public Class Computer

Dim Type as string
Dim SerialNumber as string
Dim User as String
...

End Class

Now, in my code I create two lists:

Dim DellComps as new list(of computer)
Dim HPComps as new list(of computer)

Obviously, for the DellComps, all them will have .Type = "Dell" and for the HPComps, all will have .Type = "HP"

Now, I know I could set this variable in the constructor very easily, but I'm wondering if there is a smarter way to declare the variable inside the class - Similar to the VB Shared / C# Static statement where all the instances of the class share the same variable.

My thoughts are:

  1. Inherit the class and create a shared variable in the child class
  2. Just leave it as is and declare the Type var in the constructor
  3. Maybe this is something that could be done via interfaces somehow
  4. MOST PROBABLE - something i just don't know about

Thanks and I hope what I'm asking makes sense!!!

Upvotes: 3

Views: 746

Answers (3)

Eric J.
Eric J.

Reputation: 150108

If you are always setting a flag in the constructor indicating the type of computer (which is NOT a typical business object scenario, where the type can be edited), chances are that you can really solve your problem using subclasses.

Subclass Computer to create DellComputer and HpComputer classes.

When creating lists of each type of computer, one approach is to have a master list of all computers and use Linq's Enumerable.OfType(TResult) to select instances that match the type you are interested in.

If indeed you want the type of class to be editable after the class is created, instead provide a property to modify the type of computer. You may for convenience provide a constructor overload that also sets the property (though I would shy away from that personally). If you do, have that constructor overload use the property to set the type.

UPDATE

Example of what the factory pattern might look like.

public abstract class Computer
{
    public virtual string Type { get; }
}

public class DellComputer : Computer 
{
    public override string Type 
    {
        get { return "Dell"; }
    }
}

public class HpComputer : Computer 
{
    public override string Type 
    {
        get { return "HP"; }
    }
}

// Here I'm using an enum to indicate the type desired.  You might use a string
// or anything else that makes sense in your problem domain.

public enum ComputerType
{
    Dell = 1,
    Hp = 2
}

public class ComputerFactory
{
    public Computer Create(ComputerType type)
    {
        switch (type)
        {
            case ComputerType.Dell:
                return new DellComputer();
            case ComputerType.Hp:
                return new HpComputer();
            default:
                throw new InvalidArgumentException();
        }
    }
}

// Usage would be something like:


List<Computer> computers = new List<Computer>();
computers.Add(ComputerFactory.Create(ComputerTypes.Dell);
computers.Add(ComputerFactory.Create(ComputerTypes.Dell);
computers.Add(ComputerFactory.Create(ComputerTypes.Hp);

Upvotes: 2

paparazzo
paparazzo

Reputation: 45096

You could create a class that has a collection and other data In this case PC would not have a type.

public class Computers 
{
     private List<Computer> pcs= new List<computer>();

     public List<Computer> PCs get { return { pcs; } };

     public String Brand { get; private set; }

     public Computers(string brand) {Brand = brand;}
}

Regarding a static variable. You don't want all members of the class share Brand.

With the said just repeat the data in the constructor.
If a Dell has the same Properties as an HP then I would use the same class.
If you stated buying a new brand do you really want to create a new class or subclass?
If you want a structured list of brands then I would use and Enum rather than a separate class for each brand.

Upvotes: 0

tmesser
tmesser

Reputation: 7656

The closest thing you'd have is done with the abstract keyword. You would have an abstract class Computer, that would then be overridden by the concrete subclasses DellComputer and HpComputer. A crude (C#) example would be:

public abstract class Computer
{
    public string Type { get; protected set; }
}

public class DellComputer : Computer 
{
    public DellComputer()
    {
       this.Type = "Dell"
    }
}

You generally don't want to share a single variable among a ton of instances because that breaks encapsulation, and more realistically can become a big problem when attempting to unit test code. So the pure form of what you're talking about isn't a terribly good idea, but the realistic use case is pretty common, and definitely supported.

EDIT: As part of the comments below, here's a different approach that uses the very closely related virtual keyword!

public abstract class Computer
{
    public virtual string Type { get; }
}

public class DellComputer : Computer 
{
    public override string Type 
    {
        get {
           return "Dell";
        }
    }
}

Upvotes: 5

Related Questions