C
C#2y ago
lukkasz323

❔ How can I reuse code without inheritance?

public interface IEntity
{
int Size { get; }
Vector2 Position { get; }
}
public interface IEntity
{
int Size { get; }
Vector2 Position { get; }
}
public class Player : IEntity
{
public int Size { get; } = 32;
public Vector2 Position { get; private set; }

public Player(Scene scene)
{
var spawnOffset = new Vector2(0, -3);

Position = new Vector2(
spawnOffset.X * scene.TileSize + scene.Room.Center.x - Size / 2,
spawnOffset.Y * scene.TileSize + scene.Room.Center.y - Size / 2);
}
}
public class Player : IEntity
{
public int Size { get; } = 32;
public Vector2 Position { get; private set; }

public Player(Scene scene)
{
var spawnOffset = new Vector2(0, -3);

Position = new Vector2(
spawnOffset.X * scene.TileSize + scene.Room.Center.x - Size / 2,
spawnOffset.Y * scene.TileSize + scene.Room.Center.y - Size / 2);
}
}
public class Enemy : IEntity
{
public int Size { get; } = 32;
public Vector2 Position { get; private set; }

public Enemy(Scene scene)
{
var spawnOffset = new Vector2(0, 0);

Position = new Vector2(
spawnOffset.X * scene.TileSize + scene.Room.Center.x - Size / 2,
spawnOffset.Y * scene.TileSize + scene.Room.Center.y - Size / 2);
}
}
public class Enemy : IEntity
{
public int Size { get; } = 32;
public Vector2 Position { get; private set; }

public Enemy(Scene scene)
{
var spawnOffset = new Vector2(0, 0);

Position = new Vector2(
spawnOffset.X * scene.TileSize + scene.Room.Center.x - Size / 2,
spawnOffset.Y * scene.TileSize + scene.Room.Center.y - Size / 2);
}
}
I'm trying to learn composition over inheritance, and so far so good, but the problem is that quickly there is a lot of complex code reuse, just take a look at both of these constructors, so much things I have to keep consistent between two classes. In case of inheritance I would just call the base class constructor, but what are my other possibilities here? The more of them, the better. Thanks.
8 Replies
Becquerel
Becquerel2y ago
you shouldn't spurn inheritance all the time just know what it's good for inheritance is best for is-a relationships, which your snippet seems to be a classic example of (a player is-a entity, an enemy is-a entity) composition is imo most useful for bits of actual logic and functionality - services - which you can then glue together as needed not necessarily for modelling entities to give a more pragmatic answer, though you could factor out the repeated code into a third class and use that in both to calculate positions, spawn offsets, etc
lukkasz323
lukkasz323OP2y ago
Yeah, I understand that, I'm trying to test the limits, this is mostly a learning project and I'm trying to find more alternatives.
Becquerel
Becquerel2y ago
understood, that's a worthwhile approach anyway, yeah. the composition approach is always just 'make another class to encapsulate the logic and get it through DI', basically
lukkasz323
lukkasz323OP2y ago
hmm, do you have any more specific example? A lot of open-source projects I've checked use inheritance a lot. I wonder how that could look like. My thought right now is something like this IConstructor.Construct(), which would be called in both constructors, but idk if that's something that devs actually use and I wonder if it has a better name.
Becquerel
Becquerel2y ago
i mean like this
public class PositionCreator
{
public Vector2 GetPosition(Scene scene)
{
var spawnOffset = new Vector2(0, 0);

return new Vector2(
spawnOffset.X * scene.TileSize + scene.Room.Center.x - Size / 2,
spawnOffset.Y * scene.TileSize + scene.Room.Center.y - Size / 2);
}
}

public class Enemy
{
public Enemy(PositionCreator creator)
{
Position = creator.GetPosition()
}
}
public class PositionCreator
{
public Vector2 GetPosition(Scene scene)
{
var spawnOffset = new Vector2(0, 0);

return new Vector2(
spawnOffset.X * scene.TileSize + scene.Room.Center.x - Size / 2,
spawnOffset.Y * scene.TileSize + scene.Room.Center.y - Size / 2);
}
}

public class Enemy
{
public Enemy(PositionCreator creator)
{
Position = creator.GetPosition()
}
}
forgive the formatting
lukkasz323
lukkasz323OP2y ago
Yeah, that makes sense, thanks
Becquerel
Becquerel2y ago
np
Accord
Accord2y ago
Looks like nothing has happened here. I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server