How do I refactor two classes with similar functionality?

I have classes with methods with the same names that do the same thing yet they are implemented differently.

Ex:

class converterA {
map(Item1 item1) {
// Implementation details.
}

convert(Item1 item1) {
// Implementation details.
}

translate(Item1 item1) {
// Implementation details.
}
}

class converterB {
map(Item2 item2) {
// Implementation details.
}

convert(Item2 item2) {
// Implementation details.
}

translate(Item2 item2) {
// Implementation details.
}
}

I considered using an interface but the issue is that is that the methods take in different parameters. Yet a template doesn't exactly fit either because Item1 and Item2 operate in different ways. In other words, they don't have common methods so a template doesn't exactly fit either.

Is there a solution here for refactoring the code?
What seems to be the issue?

You have two different classes. Having member variables and member functions with the same names is not uncommon. Look at the STL classes, quite often the different classes will have member functions that have the same name that do similar things with different parameters.

If they take different parameters, I would say that they don't do the same thing. Really, there's no point in trying to link the two classes together, just because they have the same purpose and function names. I'd keep them separate, though maybe mention the other as an alternative method for doing the job in the documentation.

If you do need to refactor them into the same class, for example you don't know which item type you are getting in a template function, you could just provide one class with function overloads for Item1 and Item2. If necessary, that class could then delegate to helper classes based on which overload is called.
Last edited on
I believe you can use a template interface with pure virtual functions like this. (I have done something similar in my current project and it compiles fine but I have not yet linked or debugged).

NOTE: you did not include a return type on any of your converter functions so I am providing two examples to cover both possible intentions for implementing... though I think the later one makes more sense.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// void return type
template <typename ParameterType> class IConverter
{
	virtual void map(ParameterType& parameter) = 0;
 	virtual void convert(ParameterType& parameter) = 0; 
	virtual void translate(ParameterType& parameter) = 0;
};

// OR use another typename in the template declaration for the return type
template <typename ParameterType, typename ReturnType> class IConverter
{
public:
	virtual ReturnType map(ParameterType& parameter) = 0;
	virtual ReturnType convert(ParameterType& parameter) = 0; 
	virtual ReturnType translate(ParameterType& parameter) = 0;
};



Now to declare your classes you would do it like this (for the void methods, use the analogous void template example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class AtoBConverter : public IConverter<Item1, Item2>
{
public:
	Item2 map(Item1& parameter) override; // implementation details in cpp file.
	Item2 convert(Item1& parameter) override; // implementation details in cpp file.
	Item3 translate(Item1& parameter) override; // implementation details in cpp file.

};

class BtoAConverter : public IConverter<Item2, Item1>
{
public:
	Item1 map(Item2& parameter) override; // implementation details in cpp file.
	Item1 convert(Item2& parameter) override; // implementation details in cpp file.
	Item1 translate(Item2& parameter) override; // implementation details in cpp file.

};

Last edited on
Topic archived. No new replies allowed.