Short version
You need to place the objects within the desired hierarchy to have this effect. There are two ways to do this, either through namespaces or through composition of objects.
Using the composition of objects, simply declare the properties the way you want to access them, as I show in this dotnetfiddle example. There are some problems with this code, so I talk a little more about this next.
Using the namespace hierarchy, you could declare the type Volume
within the Controle
, as you can see here, but there are also problems in this particular case.
The use of static
in your example seems to me mistaken. As well as the suggested composition itself, to access the object Volume
through the Controle
. Like the Controle
uses the Volume
, is the responsibility of the Controle
know and not who will use it.
A small improvement would be to encapsulate the volume within the control and expose only the action of controlling the volume. So:
class Controle
{
Volume volume;
public Controle()
{
volume = new Volume();
}
public void AumentarVolume()
{
volume.Aumentar();
}
}
See this example too
A little more on the subject
I may not have understood your intention correctly, but in case I have understood you take into consideration some other object orientation concepts.
So I’m going to separate into topics those that I believe are related to the example that you exposed:
Classes and Objects
In object orientation, a class defines a type that abstractly represents a concept of anything - material or not.
By following your example, imagining that we’re talking about a TV control, we could have:
- Class that abstracts TV
- Class that abstracts the control (that has multiple commands)
- Class that abstracts the command that would be sent by
Controle
(in his case, Volume
)
- Class that abstracts the interaction of control with TV (in your example,
Program
)
Objects are what makes the use of this abstraction possible. Once abstraction is defined Controle
, for example, to use it will be necessary to first create a 'material' representation of that abstraction. In object orientation this representation is given through an instance of Controle
(Controle meuControle = new Controle();
).
Bringing into the real world, the class is like the manual of control, which defines everything that type of control does. Your TV’s specific control is an instance of that control definition.
Properties, fields and methods
Classes can also define properties, fields, and methods (among other elements), which assist in controlling the object or represent its composition.
According to the intention demonstrated, to access the Volume
from the control - blindly, not considering other conceptual issues - you would have 3 options:
- Declare the
Volume
as a property of the object Controle
- Declare the
Volume
as a static property/field of the class Controle
(would not be a healthy practice in this context)
- Declare the
Volume
in namespace Controle
(would also not be healthy)
Either way you could get the desired result, but there are better ways to do it.
See a little more about Properties and fields in this answer
Classes, properties and methods Static
Essentially when we talk about static elements, it means that for that element to be used it is not necessary to have an object instance, because the static elements do not act on the object instance itself.
That question deals with this subject deeply. I recommend consulting it.
Namespace
The other way mentioned is to use the Namespace
. Among the utilities of Namespace we can highlight the contextualization of certain abstraction. This contextualization helps to restrict the scope of the solution presented in the class.
For example, supposing we were developing strategies for the game’s ghost to find the doll. Among others, we could define two strategy algorithms: 1) pursuing the path Pacman has taken or 2) trying to presume what the position of Pacman - based on the current location, speed and direction of the elements - when the ghost reaches it.
One way to organize the class that provides this algorithm would be the namespaces:
namespace Pacman.Game.Gost.Strategies
{
class PersuitPath
{
// some implementation
}
}
or
namespace Pacman.Game.Gost.Strategies
{
class EstimatePosition
{
// some implementation
}
}
Thus, access to these classes would be through namespace var estrategia = new Pacman.Game.Gost.Strategies.PersuitPath();
. It turns out that sometimes we declare the namespace on using
and we use only the element terminology within that namespace:
using Pacman.Game.Gost.Strategies;
namespace Pacman.Game
{
class Program
{
static void Main(string[] args)
{
var estrategia = new PersuitPath();
}
}
}
Abstraction
The conceptual core of object orientation is the abstraction of the real world. Thinking of the program and its behavior as an analogy of the real world contributes to the reliability of solutions.
This abstraction can occur on several levels (more concrete or more abstract) and this enables the reuse of solutions. In his example, if the solution is built according to reasoning, It would be difficult and confusing (to say the youngster) to use the class Controle
to control a Aeromodelo
, for example, for Volume
doesn’t make sense to him.
More than that, it would be possible to call the method Aumentar
or Diminuir
of Volume
without first calling the method Ligar
of Controle
?
These are examples of real-world rules that should make up your abstract model.
I hope I’ve helped.