Comments (5)
Could you please provide more information on your use case? Let's start with:
- Is this production code, or are part of it test code? If so, which ones?
- Is ImplParent an abstract class? (i.e., does it have any non-implemented virtual methods?)
- Is ImplParent only used as a base class for ImplChild (and possibly other derived classes), or are there any other places that use ImplParent?
- Is deriving from ImplParent an implementation detail of ImplChild, or are users of ImplChild allowed to know (and depend on the fact) that ImplChild is an ImplParent?
- If you drew a UML component diagram including {Interface,Impl}{Child,Parent} and the components directly using those, how would it look like? (note that multiple classes/interfaces might be in the same UML component, e.g. if ImplParent is only an implementation detail of ImplClient.) The relationships between Fruit components are closely tied to how your component diagram looks like.
from fruit.
Is this production code, or are part of it test code? If so, which ones?
Production code. What's missing, however, is the diamond. It technically looks like this.
struct InterfaceParent {};
struct ImplParent : virtual InterfaceParent {};
fruit::Component<InterfaceParent> getParent() {
return fruit::createComponent()
.install(...)
.install(...)
.install(...)
.bind<InterfaceParent, ImplParent>();
}
struct InterfaceChild : virtual InterfaceParent {};
struct ImplChild : InterfaceChild, ImplParent {};
fruit::Component<InterfaceChild> getChild() {
return fruit::createComponent()
.useInstallsFrom(getParent()) // ??? is it possible to do something like this?
.bind<InterfaceChild, ImplChild>();
}
Is ImplParent an abstract class? (i.e., does it have any non-implemented virtual methods?)
No, the parent is standalone, and can itself be injected. In this case, it's ImplParent that's used.
Is ImplParent only used as a base class for ImplChild (and possibly other derived classes), or are there any other places that use ImplParent?
Is deriving from ImplParent an implementation detail of ImplChild, or are users of ImplChild allowed to know (and depend on the fact) that ImplChild is an ImplParent?
Only used there. It's supposedly an implementation detail.
If you drew a UML component diagram
I've never done UML, sorry.
To summarize a bit on the issue, I'll take a real-world use case.
Let's say I have a "BaseModel" interface. It has a "BaseModelImpl". (Which it binds to. The impl is obviously an implementation detail). That's for the library part.
Now, I want to extend it in my application, and I'd like to have a TimestampableModel
, which has a method touch
on it, that updates the timestamps. The Impl class is TimestampableModelImpl
.
Since we don't want to redefine every single method that BaseModel
exposes in TimestampableModelImpl
(i.e. by injecting the BaseModel
in TimestampableModelImpl
, then redefining every method to forward to BaseModel
), we directly inherit BaseModelImpl
in TimestampableModelImpl
. It's all an implement detail – whoever injects TimestampableModel
(the interface) needn't care about how they're implemented.
from fruit.
Since the user of such a library (who writes TimestampableModelImpl) needs to have access to the definition of BaseModelImpl (not just to have access to a BaseModel object that happens to be a BaseModelImpl) BaseModelImpl must be exposed in the library's public interface, you can't just hide that definition in a cpp file as you'd normally do with *Impl classes when using Fruit.
You could do sth like:
// base_model.h
struct BaseModel {...};
fruit::Component<BaseModel> getBaseModelComponent();
// base_model_impl.h
// This is a *public* header, even though it has an _impl suffix!
#include "base_model.h"
struct Foo;
struct Bar;
struct BaseModelImpl : public BaseModel {
INJECT(BaseModelImpl(Foo* foo, Bar* bar)) {...}
...
};
// Use this when extending BaseModel
fruit::Component<Foo, Bar> getBaseModelDepsComponent();
// base_model.cpp
#include "foo.h"
#include "bar.h"
#include "base_model_impl.cpp"
... // Implementation of various BaseModelImpl methods
fruit::Component<Foo, Bar> getBaseModelDepsComponent() {
return fruit::createComponent()
.install(getFooComponent())
.install(getBarComponent());
}
fruit::Component<BaseModelImpl> getBaseModelComponent() {
return fruit::createComponent()
.install(getBaseModelDepsComponent())
.bind<BaseModel, BaseModelImpl>();
}
// timestampable_model.h
#include "base_model.h"
struct TimestampableModel : public Model {
virtual void touch() = 0;
};
fruit::Component<TimestampableModel> getTimestampableModelComponent();
// timestampable_model.cpp
#include "timestampable_model.h"
#include "base_model_impl.h"
#include "baz.h"
struct TimestampableModelImpl : public BaseModelImpl, public TimestampableModel {
INJECT(TimestampableModel(Foo* foo, Bar* bar, Baz* baz))
: BaseModelImpl(foo, bar) { ... }
....
};
fruit::Component<TimestampableModel> getTimestampableModelComponent() {
return fruit::createComponent()
.install(getBaseModelDepsComponent())
.install(getBazComponent())
.bind<TimestampableModel, TimestampableModelImpl>();
}
Does this structure achieve what you want?
If you want multiple levels (i.e., if you want to allow a user of the library that exposes TimestampableModel to also be able to inherit from TimestampableModelImpl), you can also have a getTimestampableModelDepsComponent() with a structure similar to the one for base_model, where you make TimestampableModelImpl part of your library's public interface.
from fruit.
Ugh, sorry. I thought we followed up on this. We went with your suggestion in the end, and it's worked well. You can close this issue.
from fruit.
Ok, happy to know that it worked for you. Closing this then.
from fruit.
Related Issues (20)
- build with vcpkg for ARM64:Android is getting errors HOT 3
- Trying to compile with NDK R22 fails HOT 11
- [Docs] Possible outdated documentation HOT 1
- Fruit does not build in Visual Studio Versions 2019, 2022 or 2022 Preview with CMake HOT 8
- what should I do to use a string as an annotion of some bind? HOT 3
- VS2022 Just My Code for Fruit Library fails using CMAKE HOT 6
- Create a fruit::Component by iterating over a list of fruit::Components HOT 7
- Can fruit be used with C language? HOT 2
- Handling lifetimes HOT 6
- Providing non-injected arguments to DI Objects HOT 14
- Build fails with Visual Studio 2022 with C++20 HOT 8
- Fruit with QT HOT 4
- Factories with reference types broken in fruit 3.7.0
- Generic binding? HOT 2
- Defining Factory Functions for Objects with Multiple Constructors HOT 11
- Replace boost HOT 1
- Creating Collections of DI Objects HOT 3
- [Suggestion] ExtractFirstError meta function SHOULD be non-error safe HOT 2
- Can no longer build examples in VS2022 Preview built by Visual Studio, VS CMake builds OK HOT 7
- Examples miss virtual dtor
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fruit.