C
C#15mo ago
.tree

❔ Issues in Repository pattern with defining Common Code

Code: https://paste.mod.gg/ybmdfcjlyxwg/0 Situation: In my code there are multiple implementations that do stuff depending on the underlying DB. Some of those DBs are open source (GeodatabasePostGIS), some are proprietary (GeodatabaseArcObjects). Because they both share some code, I made an abstract class that both inherit from (GeodatabaseAbstract). Since all open source DBs would also share specific code, I defined another abstract class only for them that inherits from GeodatabaseAbstract (GeodatabaseOpenSource). GeodatabaseAbstract implements an interface. Goal: I want to make those common code functions available to the methods of the implementations, but I cant seem to figure it out. I tried making a sort of wrapper for the abstract methods in GeodatabaseAbstract, but then I get issue regarding protection levels. Since GeodatabaseAbstract implements the Interface, I can't change the abstracts methods to anything other than public.
BlazeBin - ybmdfcjlyxwg
A tool for sharing your source code with the world!
16 Replies
phaseshift
phaseshift15mo ago
Don't use inheritance for code reuse Prefer composition over inheritance I'm really confused by your code... There's duplicates of things and no interfaces where you say there are. However, you can define common code in protected methods in abstract classes, then expose them in different public methods in the inheriting class
.tree
.tree15mo ago
Sorry, this should be the correct code: https://paste.mod.gg/jiooicbvytsm/0
BlazeBin - jiooicbvytsm
A tool for sharing your source code with the world!
.tree
.tree15mo ago
What exactly do you mean by expose? Just to call them in methods of my inheriting class?
phaseshift
phaseshift15mo ago
Expose = define public methods Are you saying your problem is you have two methods called 'common code'?
.tree
.tree15mo ago
No, my issue was this: If I have an abstract method in my abstract class AddNumbers, there is some code that I want each of my inheriting classes to do when they execute AddNumbers. Since it's abstract I cant put that code into the method itself, so I tried to define the common code in its own method and write a wrapper like "AddnumbersWrapper" that calls the common code method and the abstract method
phaseshift
phaseshift15mo ago
Yeah you can do that (wrapper). All this inheritance is really not helping though You'd be better off defining a protected/public method that calls the common method, and also calls a pure abstract method that would be specific to the implementation
abstract void ImplSpecific();

Protected void DoStuff(){

SomeStuff();
ImplSpecific ();
}

private void SomeStuff(){
//Common code
}
abstract void ImplSpecific();

Protected void DoStuff(){

SomeStuff();
ImplSpecific ();
}

private void SomeStuff(){
//Common code
}
That's if you insist on sticking with inheritance
.tree
.tree15mo ago
But when I do it like this, what would my inheriting class look like? Do I override the abstract method and call DoStuff() inside it?
phaseshift
phaseshift15mo ago
Yes (there isn't any other option given what I wrote) Wait, You don't call Do stuff inside the method you create That would be infinite recursion You might call DoStuff inside your inheriting class, but not inside ImplSpecific
.tree
.tree15mo ago
So in my example
c#
public abstract class GeodatabaseAbstract {
public abstract int AddNumbers(int a, int b);

protected void DoAddNumbers(int a, int b) {
CommonCode();
AddNumbers(a, b);
}

private void CommonCode() {
// common code
}
}
c#
public abstract class GeodatabaseAbstract {
public abstract int AddNumbers(int a, int b);

protected void DoAddNumbers(int a, int b) {
CommonCode();
AddNumbers(a, b);
}

private void CommonCode() {
// common code
}
}
The inheriting class would be
c#
public class GeodatabaseArcObjects : GeodatabaseAbstract {
public override int AddNumbers(int a, int b) {
int c = a + b;
return c;
}
}
c#
public class GeodatabaseArcObjects : GeodatabaseAbstract {
public override int AddNumbers(int a, int b) {
int c = a + b;
return c;
}
}
Where would I call DoAddNumbers now? My ArcObjects specific implementation of AddNumbers still needs to be there, but how do I tell it to do common code and then the specifig AddNumbers?
phaseshift
phaseshift15mo ago
Add Numbers shouldn't be public DoAddNumbers would be the public method in your example
.tree
.tree15mo ago
What should AddNumbers be? Protected? The issue with that is that the Interface complains, since it defines AddNumbers and wants it to be public
phaseshift
phaseshift15mo ago
Yeah it's just naming Whatever you want as public need to be in the interface Like you can just swap the names to solve that issue
.tree
.tree15mo ago
Yeah makes sense. So the DoAddNumbers in my inheriting class has to be protected now since the abstract method in my abstract class is protected too. So it looks like this now:
c#
public abstract class GeodatabaseAbstract : IGeodatabase
{
protected abstract int DoAddNumbers(int a, int b);

public int AddNumbers(int a, int b)
{
CommonCode();
return DoAddNumbers(a, b);
}
private void CommonCode()
{
// Common code for all DBs
Console.WriteLine("Yeah boi");
}
}
c#
public abstract class GeodatabaseAbstract : IGeodatabase
{
protected abstract int DoAddNumbers(int a, int b);

public int AddNumbers(int a, int b)
{
CommonCode();
return DoAddNumbers(a, b);
}
private void CommonCode()
{
// Common code for all DBs
Console.WriteLine("Yeah boi");
}
}
c#
public class GeodatabaseArcObjects : GeodatabaseAbstract
{
protected override int DoAddNumbers(int a, int b)
{
int c = a + b;
return c;
}
}
c#
public class GeodatabaseArcObjects : GeodatabaseAbstract
{
protected override int DoAddNumbers(int a, int b)
{
int c = a + b;
return c;
}
}
Now when I call it like this:
c#
IGeodatabase geodatabaseAccess = new GeodatabaseArcObjects();
Console.WriteLine(geodatabaseAccess.AddNumbers(1,2));
c#
IGeodatabase geodatabaseAccess = new GeodatabaseArcObjects();
Console.WriteLine(geodatabaseAccess.AddNumbers(1,2));
It uses the public AddNumbers from my abstract, does the common code, then it calls DoAddNumbers which is abstract, so it uses the specific implementation it has itself?
phaseshift
phaseshift15mo ago
Right
.tree
.tree15mo ago
Its really not that hard once you think about it a little, thank you for your help!
Accord
Accord15mo ago
Looks like nothing has happened here. I will mark this as stale and this post will be archived until there is new activity.