Tony D
Tony D

Reputation: 1531

Nested Class Conundrum

For simplicity let's say I have two classes: a class called Car and a collection class called Tires. Tires is a nested class inside the Car class. I want to give my clients access to the collection - i.e. they should be able to iterate over it:

foreach( var tire in car.tires ) ...

and access each tire's properties. But I don't want to give them access to the methods in tires. I want all access to behavior to come through the Car class:

car.FillTires();

Scenario 1: Tires class is public with methods private: Car class can't access Tire methods.
Scenario 2: Tires class is private with methods public: I can't expose the collection to my clients.
Internal doesn't work for me either as I don't want to grant other classes in the assembly access.

Upvotes: 4

Views: 210

Answers (4)

Joren
Joren

Reputation: 14746

A simple solution is to re-evaluate if Tires should be an inner class. If you make it a normal class you can simply use internal and public to differentiate between what clients and what Car can access.

If there is an unrelated reason why Tires should be an inner class, expose only a read-only version:

  • Expose a copy like CMP suggests (doesn't need to be a different class, although it's indeed better to, so you can throw exceptions). I like this suggestion the least, because it's inelegant to have a class that looks like you can mutate it while actually you can't.
  • Make the whole class immutable like Danny suggests, which is effective and neat, but makes it less convenient to deal with (needing to overwrite the old instance in Car with a new one every time you want to change something.)
  • Expose the class only through a read-only interface like Asaph suggests. I like this best because it allows Car complete control while limiting public access without any inconvenience or copying.

Upvotes: 3

captncraig
captncraig

Reputation: 23138

You may write class FakeTire that extends Tire.

Override FillTires to throw an exception in FakeTire class. Car has a list of real tires, but it's Tires property creates a list of Faketires to give out. Kindof like a read only collection.

Upvotes: 0

Danny Varod
Danny Varod

Reputation: 18118

Option 1: You could put Car in a separate assembly and use scenario 1ish (Tire could be public + methods internal).

Option 2: You could make Tire immutable (like String) and let consumers do what ever they want with tires, but they can not change the tires within the car (make the tires collection's property readonly but do not make the private backing field readonly).

Upvotes: 2

Asaph
Asaph

Reputation: 162851

Create an interface with only the methods you wish to clients to access and expose a collection of the interface type through your class's methods.

Upvotes: 3

Related Questions