I'm making a map loading system that uses chunks so that the entire map data doesn't have to be loaded at once.
I have a "World" class, and within that class I'm creating an instance of a class called "ChunkManager".
I'm unsure if creating an instance inside another class is a good idea/considered a "normal" thing to do etc. I've not been able to find anything about this while searching the internet.
So my question is: Should I be creating an instance of a class within a class in the way I have, or will there be problems with doing it this way?
Here is my code, if it's relevant:
class World
{
public string WorldName { get; set; }
ChunkManager chunkManager = new ChunkManager();
public World(string worldName)
{
WorldName = worldName;
}
public void AddChunk(int X, int Y)
{
//Plus other validation code here that I didn't paste
chunkManager.AddChunk(X, Y);
}
}
And ChunkManager:
class ChunkManager
{
public int TotalGeneratedChunks { get; private set; }
private List<Chunk> ChunkList = new List<Chunk>();
public bool CheckIDExists(int IDToCheck)
{
foreach (Chunk i in ChunkList)
{
if (i.UniqueID == IDToCheck)
{
return true;
}
}
return false;
}
public void AddChunk(int X, int Y)
{
ChunkList.Add(new Chunk(TotalGeneratedChunks++, X, Y));
}
}
-
3There is absolutely no problem in doing this,fhnaseer– fhnaseer2013年09月20日 03:07:40 +00:00Commented Sep 20, 2013 at 3:07
-
Is it working the way you'd expect?OneFineDay– OneFineDay2013年09月20日 03:08:13 +00:00Commented Sep 20, 2013 at 3:08
-
If you had read any code at all in your travels you would have seen this exact thing done in every bit of code you saw. When you something as simple as creating/initialising a new string you are "creating an object within a class" as you put it.slugster– slugster2013年09月20日 03:19:33 +00:00Commented Sep 20, 2013 at 3:19
-
No problem with doing this. But using dependency injection would be a good idea as well.Brent Mannering– Brent Mannering2013年09月20日 03:21:20 +00:00Commented Sep 20, 2013 at 3:21
-
There is no issue with this approach as long as you recognize you're tightly coupling your class to that implementation of ChunkManager. Remember: New is Glue! ardalis.com/new-is-gluessmith– ssmith2017年09月22日 12:12:56 +00:00Commented Sep 22, 2017 at 12:12
5 Answers 5
Your code is fine BUT if either class grows to be more complex and you want to be able to test them independently you should instead define an interface IChunkmanager and inject an instance of ChunkManager into World:
class World
{
public string WorldName { get; set; }
private readonly IChunkManager chunkManager;
public World(string worldName, IChunkManager chunkmanager)
{
this.chunkManager = chunkManager;
...
With this approach you can use a mocking framework to inject a mock IChunkManager
and can test the World
class independently.
In general classes should be loosely coupled. As soon as you new-up an instance of another class within a class you have tightly-bound them in a way that makes it hard to test them independently (or to reuse them in different situations).
-
2~2 years later and after I've improved my knowledge a lot more and I understand dependency injection and interfaces, I understand your answer a lot more. Thanks!user9993– user99932016年05月30日 14:31:32 +00:00Commented May 30, 2016 at 14:31
It's perfectly fine to create an instance of a class inside another. chunkManager
is what is known as a field
and the syntax for initializing it inline along with its declaration is called an initializer
. You can find more information on initializers and how they are different from initializing via the constructor in this blog series by Eric Lippert
It might some times be a better idea to initialize fields via the constructor though as this lets you use dependency injection (parameter injection to be precise) which can greatly improve the testability and modularity of your code. If you're interested in learning more about dependency injection I suggest purchasing and reading this book.
Standard practice is to set values inside the constructor because it allows for dependency injection and makes modifying the constructor to use an argument trivially easy.
If you are going to create a lot of World, i suggest creating an Abstract base that implements the ChunckManager.
That way you can leverage the use of base class, promote code reuse. You can also make your ChunkManager singleton since it only needs to be used by the base, and then use a method to actually instantiate the ChunkManager if you need specific properties from maps.
Use DI to pass the prop from child to base to instantiation of the ChunkManager
yes you can use one class type in another class its like one of filed on this class like when you use string a=new string() you use an object of class string its normal code