views:

108

answers:

5

Hi,

Let's say we have a class called A and another one called B. and we want to have a conversion method that converts A to B.

In the software architecture point of view, which one is preferred?

  1. write A.export()
  2. write B.import()
  3. write a converter class, i.e. convert(A, B) or Convert(A) or ...

if the language matters, I'm using C++

Thanks,

+6  A: 

It entirely depends on how you intend to use it, but in many cases, the cleanest way to do this is to implement a converting constructor:

class B { };
class A
{
    A(const B& b) { }
};

B b;
A a = b; //< calls converting constructor

(of course, you could implement a converting constructor for converting from A to B, as well)

James McNellis
Yep, I agree. Thanks :)
Nima
Anders Abel
Yes, I think that's exactly what I need. Thanks again
Nima
@Anders: That's true, though I don't think I've ever had a major issue caused by implicit conversion (except in C++/CLI, which doesn't count ;-P); I tend to prefer non-explicit constructors for conversion because it often makes for much cleaner code. If the constructor is explicit, it's often more work to use than just creating a nonmember function that does the conversion.
James McNellis
@James: If I wrote a non-`explicit` conversion constructor, I'd be afraid that I'd forget about it, and have a nasty bug a year or two down the line.
David Thornley
+1  A: 

If we take a short look at Java (just for information, even though you are using C++):

Say that class A is String and class B is Integer (or Double, Boolean, et c). The Java library designers have put a static method in Integer ("B") called getInteger ("import") that takes a String ("A") and produces an Integer ("B"). That would be your case 2.

On the other hand, in every class (call them "A") there is a method toString ("export") that returns a String ("B"). That would be your case 1.

So even for such basic classes, they decided to use different ways. I guess that means the same thing as @James McNellis said: it depends.

Peter Jaric
Nice comparison. Thanks
Nima
+2  A: 

First of all, decide whether a conversion between them is really natural and intuitive. In that case, you could use a constructor or a member function.

However, if the connection is not too natural, you may want to go with a separate ConversionUtils class with conversion methods or something like this. You don't want to start creating too many dependencies between classes or end up implementing n*n conversions.

It is also important to be careful with "conversion constructors", as they can be invoked without you realizing it. For example, if I have an a and a b and I write something like a==b, the presence of a constructor in A or B that takes the other could result in successful compilation with no warning, and possibly interesting results at runtime. I would strongly encourage you to make your constructor explicit in these cases.

Uri
Yes, exactly. I also got the same point.It's completely based on the intrinsic relation between them.For example in my case, I have two objects that store a Vertex, one is used for in-core algorithms and a DiskVertex for out-of-core manipulatios.I think in this case, I'd better write the explicit conversion.
Nima
@Nima: If the DiskVertex is one possible representation of a Vertex, then definitely don't change Vertex. You may want to make it a disk vertex with a constructor that takes normal vertices, though I'm usually careful about that.
Uri
A: 

You can overload cast operators, i.e., operator T () { .. return a T value }. Whether or not you should is another matter.

DeadMG
A: 

I would use your third suggestion. A separate converter class for the conversion. This way you don't directly coupled A to B or B to A. A and B will have their own responsibilities whatever it is.

The converter class C its responsibility is purely conversion. Each class will be responsible for a single thing which in my opinion is a good thing. I believe this is the S in the SOLID design principles (Single Responsibility principle).

kalkie