问题描述:

In exposing the C++ (or Java) interface of a library, one has to provide the "private" fields of classes, and this is understable, because the compiler needs to know the structure of the class, in order to be able to compute, for example, sizeof().

But why this is needed and how could be alleviated? Because, for me, it appears as a breach in the encapsulation concept: why the user shall worry or have access to something that is considered to be private?

One solution would be to define a size() function for each object, but this will be burdensome at runtime.

Still, one language (eC/ecere) claims that [1]:

"Library developers don't need to worry about the private content of the class definition being seen by the end user, only what is declared public will be visible"

How is that achieved in eC and how could similar be implemented in Java or C++?

[1] http://www.ecere.com/technologies.html

网友答案:

Just because the programmer or the compiler can "see" a private type, doesn't mean it violates "encapsulation". Consider encapsulation as a "contract" (you're not supposed to use it, but you can still see it).

... HOWEVER ...

the answer to your question, if you really want to "hide" the underlying representation, is to use opaque pointers:

  • http://en.wikipedia.org/wiki/Opaque_data_type

  • http://en.wikipedia.org/wiki/Opaque_pointer

Here's an example in C++:

http://www.tilander.org/aurora2/Stupid_Cpp_Tricks/index.html

One of the early books I bought on C++ was James Coplien's 'Acid Book' (as Meyers calls it). Much of the stuff in there is today more bread and butter things, although it you haven't read it, you should. One of the things James (or Jim, how nice of a name is that) introduced was the Pimpl idom. Private Implementation is a happy interpretation of the weird name, the more plausible is pointer to implementation. In simple terms it's a compiler firewall, or an opaque type that effectively hides the implementation of any class from the outside.

// in the header
class Foo
{
public:
    Foo();
    ~Foo();

private:
    struct Pimpl; // forward declaration to internal structure
    Pimpl* m; // opaque pointer to actual data
};

// in the cpp file
struct Foo::Pimpl
{
    std::string name;
};

Foo::Foo()
    : m( new Pimpl)
{
}

Foo::~Foo()
{
    delete m;
}
网友答案:

You can easily achieve encapsulation by exposing only interfaces, not the implementation. In C++ interface is just a class with only pure virtual methods:

class Interface
{
public:
    virtual void method() = 0;
};

If your API is based on interfaces, besides encapsulation it will be also more modular and flexible, less coupled and more testable. So it's highly desirable to use interfaces in the API instead of implementation classes.

Of course you will have to use factories, builders and other design patterns to construct the real instances implementing interfaces.

网友答案:

eC has a runtime reflection model which is aware of the layout of all classes, and distinguishes between struct (always allocated in place) and classes (classes are always allocated on the heap, by the runtime mechanism aware of the class layouts).

The idea behind this is that small objects that may be numerous and/or contiguous (e.g. a Point) are better suited for a struct, whereas more complex object that will require memory management are better suited for a class. This can also allow swapping libraries with identical interface but completely different layout.

The need for C++ 'pimpl' is just one of those things I could not stand about C++ (another one being header files) which had me design eC, after being dissatisfied trying to build a C++ class library for Ecere.

I've seen C++ code proliferate to 4 different files for API, API header, Implementation, Implementation header with many lines in each instead of simply in eC:

public class MyClass
{
   public int myFunction() {  }
   private int myPrivateMember;  
}

Btw eC has a new website :) http://ec-lang.org (still to be improved). And I'm always happy to answer questions and help out on the forums and IRC!

相关阅读:
Top