What is the C/C++ equivalence of java.io.Serializable?
There're references to serialization libraries on:
Serialize Data Structures in C
And there are:
http://troydhanson.github.io/tpl/index.html
http://www.boost.org/doc/libs/1_41_0/libs/serialization/doc/index.html
https://developers.google.com/protocol-buffers/docs/cpptutorial#optimization-tips
But do such an equivalence even exists?
So if I have an abstract class as follows in Java, how would a serializable class in C/C++ look like?
import java.io.Serializable;
public interface SuperMan extends Serializable{
/**
* Count the number of abilities.
* #return
*/
public int countAbility();
/**
* Get the ability with index k.
* #param k
* #return
*/
public long getAbility(int k);
/**
* Get the array of ability from his hand.
* #param k
* #return
*/
public int[] getAbilityFromHand(int k);
/**
* Get the finger of the hand.
* #param k
* #return
*/
public int[][] getAbilityFromFinger(int k);
//check whether the finger with index k is removed.
public boolean hasFingerRemoved(int k);
/**
* Remove the finger with index k.
* #param k
*/
public void removeFinger(int k);
}
Could any serializable C/C++ object just be inherited like in Java?
There are no standard library classes that implement serialization the same way Java does. There are some libraries that facilitate serialization but for basic needs you typically make your class serializable by overloading the insertion and extraction operators like this:
class MyType
{
int value;
double factor;
std::string type;
public:
MyType()
: value(0), factor(0.0), type("none") {}
MyType(int value, double factor, const std::string& type)
: value(value), factor(factor), type(type) {}
// Serialized output
friend std::ostream& operator<<(std::ostream& os, const MyType& m)
{
return os << m.value << ' ' << m.factor << ' ' << m.type;
}
// Serialized input
friend std::istream& operator>>(std::istream& is, MyType& m)
{
return is >> m.value >> m.factor >> m.type;
}
};
int main()
{
std::vector<MyType> v {{1, 2.7, "one"}, {4, 5.1, "two"}, {3, 0.6, "three"}};
std::cout << "Serialize to standard output." << '\n';
for(auto const& m: v)
std::cout << m << '\n';
std::cout << "\nSerialize to a string." << '\n';
std::stringstream ss;
for(auto const& m: v)
ss << m << '\n';
std::cout << ss.str() << '\n';
std::cout << "Deserialize from a string." << '\n';
std::vector<MyType> v2;
MyType m;
while(ss >> m)
v2.push_back(m);
for(auto const& m: v2)
std::cout << m << '\n';
}
Output:
Serialize to standard output.
1 2.7 one
4 5.1 two
3 0.6 three
Serialize to a string.
1 2.7 one
4 5.1 two
3 0.6 three
Deserialize from a string.
1 2.7 one
4 5.1 two
3 0.6 three
The serialization format is entirely up to the programmer and you are responsible for making sure that each member of the class that you want to serialize is itself serializable (has an insertion/extraction operator defined). You also have to deal with how fields are separated (spaces or new-lines or zero-terminated?).
All the basic types have serialization (insertion/extraction) operators pre-defined but you still need to be careful with things like std::string that can contain (for example) spaces or new-lines (if you are using spaces or new-lines as your field delimiter).
There is not a single standard for this. In fact every library can implement it in different way. Here are some approaches which can be used:
class has to be derived from common base class and implement read() and write() virtual methods:
class SuperMan : public BaseObj
{
public:
virtual void read(Stream& stream);
virtual void write(Stream& stream);
};
class should implement special interface - in C++ this is done by deriving class from special abstract class. This is variaton of previous method:
class Serializable
{
public:
virtual Serializable() {}
virtual void read(Stream& stream) = 0;
virtual void write(Stream& stream) = 0;
};
class SuperMan : public Man, public Serializable
{
public:
virtual void read(Stream& stream);
virtual void write(Stream& stream);
};
library may allow (or require) to register "serializers" for given type. They can be implemented by creating class from special base class or interface, and then registering them for given type:
#define SUPERMAN_CLASS_ID 111
class SuperMan
{
public:
virtual int getClassId()
{
return SUPERMAN_CLASS_ID;
}
};
class SuperManSerializer : public Serializer
{
virtual void* read(Stream& stream);
virtual void write(Stream& stream, void* object);
};
int main()
{
register_class_serializer(SUPERMAN_CLASS_ID, new SuperManSerializer());
}
serializers can be also implemented using functors, e.g. lambdas:
int main
{
register_class_serializer(SUPERMAN_CLASS_ID,
[](Stream&, const SuperMan&) {},
[](Stream&) -> SuperMan {});
}
instead of passing serializer object to some function, it may be enough to pass its type to special template function:
int main
{
register_class_serializer<SuperManSerializer>();
}
class should provide overloaded operators like '<<' and '>>'. First argument for them is some stream class, and second one is out class instance. Stream can be a std::stream, but this causes conflict with default use for these operators - converting to and from user-friendly text format. Because of this stream class is a dedicated one (it can wrap std::stream though), or library will support alternative method if << also has to be supported.
class SuperMan
{
public:
friend Stream& operator>>(const SuperMan&);
friend Stream& operator<<(const SuperMan&);
};
there should be specialization of some class template for our class type. This solution can be used together with << and >> operators - library first will try to use this template, and revert to operators if it will not be specialized (this can be implemented as default template version, or using SFINAE)
// default implementation
template<class T>
class Serializable
{
public:
void read(Stream& stream, const T& val)
{
stream >> val;
}
void write(Stream& stream, const T& val)
{
stream << val;
}
};
// specialization for given class
template<>
class Serializable<SuperMan>
{
void read(Stream& stream, const SuperMan& val);
void write(Stream& stream, const SuperMan& val);
}
instead of class template library may also use C-style interface with global overloaded functions:
template<class T>
void read(Stream& stream, const T& val);
template<class T>
void write(Stream& stream, const T& val);
template<>
void read(Stream& stream, const SuperMan& val);
template<>
void write(Stream& stream, const SuperMan& val);
C++ language is flexible, so above list is for sure not complete. I am convinced it would be possible to invent another solutions.
As other answers have mentioned, C++ does not have nearly the sort of built-in serialization/deserialization capabilities that Java (or other managed languages) have. This is in part due to the minimal run-time type information (RTTI) available in C++. C++ by itself does not have reflection, so each serializable object must be completely responsible for serialization. In managed languages like Java and C#, the language includes enough RTTI for an external class to be able to enumerate the public fields on an object in order to perform the serialization.
Luckily... C++ does not impose a default mechanism for serialization of a class hierarchy. (I wouldn't mind it supplying an optional mechanism supplied by a special base type in the standard library or something, but overall this could put limits on existing ABIs)
YES Serialization is incredibly important and powerful in modern software engineering. I use it any time I need to translate a class hierarchy to and from some form of runtime consumable data. The mechanism I always choose is based on some form of reflection. More on this below.
You may also want to look here for an idea of the complexities to consider and if you really wanted to verify against the standard you could purchase a copy here. It looks like the working draft for the next standard is on github.
Application specific systems
C++/C allow the author of the application the freedom to select the mechanics behind many of the technologies people take for granted with newer and often higher level languages. Reflection (RTTI), Exceptions, Resource/Memory Management (Garbage collection, RAII, etc.). These systems can all potentially impact the overall quality of a particular product.
I have worked on everything from real time games, embedded devices, mobile apps, to web applications and the overall goals of the particular project vary between them all.
Often for real time high performance games you will explicitly disable RTTI (it isn't very useful in C++ anyway to be honest) and possibly even Exceptions (Many people don't desire the overhead produced here either and if you were really crazy you could implement your own form from long jumps and such. For me Exceptions create an invisible interface that often creates bugs people wouldn't even expect to be possible, so I often avoid them anyway in favor of more explicit logic. ).
Garbage collection isn't included in C++ by default either and in real time games this is a blessing. Sure you can have incremental GC and other optimized approaches which I have seen many games use (often times it is a modification of an existing GC like that used in Mono for C#). Many games use pooling and often for C++ RAII driven by smart pointers. It isn't unusual to have different systems with different patterns of memory usage either which can be optimized in different ways. The point is some applications care more then others about the nitty gritty details.
General idea of automatic serialization of type hierarchy
The general idea of an automatic serialization system of type hierarchies is to use a reflection system that can query type information at runtime from a generic interface. My solution below relies on building that generic interface by extending upon some base type interfaces with the help of the macros. In the end you basically get a dynamic vtable of sorts that you can iterate by index or query by string names of members/types.
I also use a base reflection reader/writer type that exposes some iostream interfaces to allow derived formatters to override. I currently have a BinaryObjectIO, JSONObjectIO, and ASTObjectIO but it is trivial to add others. The point of this is to remove the responsibly of serializing a particular data format from the hierarchy and put it into the serializer.
Reflection at the language level
In many situations the application knows what data it would like to serialize and there is no reason to build it into every object in the language. Many modern languages include RTTI even in the basic types of the system (if they are type based common intrinsics would be int, float, double, etc.). This requires extra data to be stored for everything in the system regardless of the usage by the application. I'm sure many modern compilers can at times optimize away some with tree shaking and such, but you can't guarantee that either.
A Declarative approach
The methods already mentioned are all valid use cases, although they lack some flexibility by having the hierarchy handle the actual serialization task. This can also bloat your code with boilerplate stream manipulation on the hierarchy.
I personally prefer a more declarative approach via reflection. What I have done in the past and continue to do in some situations is create a base Reflectable type in my system. I end up using template metaprogramming to help with some boilerplate logic as well as the preprocessor for string concatenation macros. The end result is a base type that I derive from, a reflectable macro declaration to expose the interface and a reflectable macro definition to implement the guts (tasks like adding the registered member to the type's lookup table.).
So I normally end up with something that looks like this in the h:
class ASTNode : public Reflectable
{
...
public:
DECLARE_CLASS
DECLARE_MEMBER(mLine,int)
DECLARE_MEMBER(mColumn,int)
...
};
Then something like this in the cpp:
BEGIN_REGISTER_CLASS(ASTNode,Reflectable);
REGISTER_MEMBER(ASTNode,mLine);
REGISTER_MEMBER(ASTNode,mColumn);
END_REGISTER_CLASS(ASTNode);
ASTNode::ASTNode()
: mLine( 0 )
, mColumn( 0 )
{
}
I can then use the reflection interface directly with some methods such as:
int id = myreflectedObject.Get<int>("mID");
myreflectedObject.Set( "mID", 6 );
But much more commonly I just iterate some "Traits" data that I have exposed with another interface:
ReflectionInfo::RefTraitsList::const_iterator it = info->getReflectionTraits().begin();
Currently the traits object looks something like this:
class ReflectionTraits
{
public:
ReflectionTraits( const uint8_t& type, const uint8_t& arrayType, const char* name, const ptrType_t& offset );
std::string getName() const{ return mName; }
ptrType_t getOffset() const{ return mOffset; }
uint8_t getType() const{ return mType; }
uint8_t getArrayType() const{ return mArrayType; }
private:
std::string mName;
ptrType_t mOffset;
uint8_t mType;
uint8_t mArrayType; // if mType == TYPE_ARRAY this will give the type of the underlying data in the array
};
I have actually come up with improvements to my macros that allow me to simplify this a bit... but those are taken from an actual project I'm working on currently. I'm developing a programming language using Flex, Bison, and LLVM that compiles to C ABI and webassembly. I'm hoping to open source it soon enough, so if you are interested in the details let me know.
The thing to note here is that "Traits" information is metadata that is accessible at runtime and describes the member and is often much larger for general language level reflection. The information I have included here was all I needed for my reflectable types.
The other important aspect to keep in mind when serializing any data is version information. The above approach will deserialize data just fine until you start changing the internal data structure. You could, however, include a post and possibly pre data serialization hook mechanism with your serialization system so you can fix up data to comply with newer versions of types. I have done this a few times with setups like this and it works really well.
One final note about this technique is that you are explicitly controlling what is serialized here. You can pick and choose the data you want to serialize and the data that may just be keeping track of some transient object state.
C++ Lax guarantees
One thing to note... Since C++ is VERY lax about what data actually looks like. You often have to make some platform specific choices (this is probably one of the main reasons a standard system isn't provided). You can actually do a great deal at compile time with Template metaprogramming, but sometimes it is easier to just assume your char to be 8 bits in length. Yes even this simple assumption isn't 100% universal in C++, luckily in most situations it is.
The approach I use also does some non-standard casting of NULL pointers to determine memory layout (again for my purposes this is the nature of the beast). The following is an example snippet from one of the macro implementations to calculate the member offset in the type where CLASS is provided by the macro.
(ptrType_t)&reinterpret_cast<ptrType_t&>((reinterpret_cast<CLASS*>(0))->member)
A general warning about reflection
The biggest issue with reflection is how powerful it can be. You can quickly turn an easily maintainable codebase into a huge mess with too much inconsistent usage of reflection.
I personally reserve reflection for lower level systems (primarily serialization) and avoid using it for runtime type checking for business logic. Dynamic dispatching with language constructs such as virtual functions should be preferred to reflection type check conditional jumps.
Issues are even harder to track down if the language has inherit all or nothing support for reflection as well. In C# for example you cannot guarantee, given a random codebase, that a function isn't being used simply by allowing the compiler to alert you of any usage. Not only can you invoke the method via a string from the codebase or say from a network packet... you also could break the ABI compatibility of some other unrelated assembly that reflects on the target assembly. So again use reflection consistently and sparingly.
Conclusion
There is currently no standard equivalent to the common paradigm of a serializable class hierarchy in C++, but it can be added much like any other system you see in newer languages. After all everything eventually translates down to simplistic machine code that can be represented by the binary state of the incredible array of transistors included in your CPU die.
I'm not saying that everyone should roll their own here by any means. It is complicated and error prone work. I just really liked the idea and have been interested in this sort of thing for a while now anyways. I'm sure there are some standard fallbacks people use for this sort of work. The first place to look for C++ would be boost as you mentioned above.
If you do a search for "C++ Reflection" you will see several examples of how others achieve a similar result.
A quick search pulled up this as one example.
Related
Say I have a List of object which were defined using lambda expressions (closures). Is there a way to inspect them so they can be compared?
The code I am most interested in is
List<Strategy> strategies = getStrategies();
Strategy a = (Strategy) this::a;
if (strategies.contains(a)) { // ...
The full code is
import java.util.Arrays;
import java.util.List;
public class ClosureEqualsMain {
interface Strategy {
void invoke(/*args*/);
default boolean equals(Object o) { // doesn't compile
return Closures.equals(this, o);
}
}
public void a() { }
public void b() { }
public void c() { }
public List<Strategy> getStrategies() {
return Arrays.asList(this::a, this::b, this::c);
}
private void testStrategies() {
List<Strategy> strategies = getStrategies();
System.out.println(strategies);
Strategy a = (Strategy) this::a;
// prints false
System.out.println("strategies.contains(this::a) is " + strategies.contains(a));
}
public static void main(String... ignored) {
new ClosureEqualsMain().testStrategies();
}
enum Closures {;
public static <Closure> boolean equals(Closure c1, Closure c2) {
// This doesn't compare the contents
// like others immutables e.g. String
return c1.equals(c2);
}
public static <Closure> int hashCode(Closure c) {
return // a hashCode which can detect duplicates for a Set<Strategy>
}
public static <Closure> String asString(Closure c) {
return // something better than Object.toString();
}
}
public String toString() {
return "my-ClosureEqualsMain";
}
}
It would appear the only solution is to define each lambda as a field and only use those fields. If you want to print out the method called, you are better off using Method. Is there a better way with lambda expressions?
Also, is it possible to print a lambda and get something human readable? If you print this::a instead of
ClosureEqualsMain$$Lambda$1/821270929#3f99bd52
get something like
ClosureEqualsMain.a()
or even use this.toString and the method.
my-ClosureEqualsMain.a();
This question could be interpreted relative to the specification or the implementation. Obviously, implementations could change, but you might be willing to rewrite your code when that happens, so I'll answer at both.
It also depends on what you want to do. Are you looking to optimize, or are you looking for ironclad guarantees that two instances are (or are not) the same function? (If the latter, you're going to find yourself at odds with computational physics, in that even problems as simple as asking whether two functions compute the same thing are undecidable.)
From a specification perspective, the language spec promises only that the result of evaluating (not invoking) a lambda expression is an instance of a class implementing the target functional interface. It makes no promises about the identity, or degree of aliasing, of the result. This is by design, to give implementations maximal flexibility to offer better performance (this is how lambdas can be faster than inner classes; we're not tied to the "must create unique instance" constraint that inner classes are.)
So basically, the spec doesn't give you much, except obviously that two lambdas that are reference-equal (==) are going to compute the same function.
From an implementation perspective, you can conclude a little more. There is (currently, may change) a 1:1 relationship between the synthetic classes that implement lambdas, and the capture sites in the program. So two separate bits of code that capture "x -> x + 1" may well be mapped to different classes. But if you evaluate the same lambda at the same capture site, and that lambda is non-capturing, you get the same instance, which can be compared with reference equality.
If your lambdas are serializable, they'll give up their state more easily, in exchange for sacrificing some performance and security (no free lunch.)
One area where it might be practical to tweak the definition of equality is with method references because this would enable them to be used as listeners and be properly unregistered. This is under consideration.
I think what you're trying to get to is: if two lambdas are converted to the same functional interface, are represented by the same behavior function, and have identical captured args, they're the same
Unfortunately, this is both hard to do (for non-serializable lambdas, you can't get at all the components of that) and not enough (because two separately compiled files could convert the same lambda to the same functional interface type, and you wouldn't be able to tell.)
The EG discussed whether to expose enough information to be able to make these judgments, as well as discussing whether lambdas should implement more selective equals/hashCode or more descriptive toString. The conclusion was that we were not willing to pay anything in performance cost to make this information available to the caller (bad tradeoff, punishing 99.99% of users for something that benefits .01%).
A definitive conclusion on toString was not reached but left open to be revisited in the future. However, there were some good arguments made on both sides on this issue; this is not a slam-dunk.
To compare labmdas I usually let the interface extend Serializable and then compare the serialized bytes. Not very nice but works for the most cases.
I don't see a possibility, to get those informations from the closure itself.
The closures doesn't provide state.
But you can use Java-Reflection, if you want to inspect and compare the methods.
Of course that is not a very beautiful solution, because of the performance and the exceptions, which are to catch. But this way you get those meta-informations.
My design problem is that I'm trying to write a general class that would fit several possible subtypes. Specifically, I'm trying to write a Node class for a binary search tree, that would fit several implementations of search trees (Avl Tree, 2-3 Tree, Red-Black tree, etc.) My problem is: different Trees require different variables in the Node class in order to maintain efficiency. AvlTree need a height variable, RedBlackTree need a color variable (which an AvlTree have no use for), and so on. What's the best design solution:
declare many variables in the Node (color, height, balancing factor,...), and just give many constructors?
Have a a variable of type Object in Node, called metadata, which every implementation will use to contain its metadata?
Something else?
How to design a general Node for a Binary Search Tree?
ok, you asked...
First, that is a great link below there. And will certainly expose
the breadth of your question, strictly keeping to Data Structs.
Abstract_Hierarchies make everything so much easier.
At least you are thinking in the right direction. As I see some have mentioned here, at least superficially, the best approach (Language Agnostic) is always the same in OOP.
By the way, Java is an excellent language, to begin practicing OOP principles. In fact, I just deleted that paragraph...
IFace, IFaces, FullInterface. The secret to building any good abstract hierarchy is 'bare bones' implementation.
(I won't implement the generics here, but Java has robust support just for this. java.util.collection this is the root of the collections hierarchy).
However, generics are virtually built into the language for you. Everything is an Object in Java. There you go...The most abstract representation of any type you can imagine.
To your specific requirements: in pseudo...or pseudo-pseudo
that's all I was ever able to grasp. The pseudo-pseudo(whatever).
INode must have at least:
One Private DATA member or Key.
Reference to at LEAST, BUT at this point, not more than 2.
Child INodes(a minor inconvenience here. java does not
give users direct access to memory via pointers, like
C/C++) Obviously, this is exactly 2, but 'AT LEAST' is a
very important methodology when thinking about progressive
implementation. Just the absolute essence, no more.
Public accessor and mutator for private DATA.
Manager function Declarations.(short list, I don't recall
whether or not operator overloading is supported in java or not)
Can't imagine how the op equals is handled, given the case...hmmm
Since an INode is useless(not entireley) apart from its Data
structure, This is where I would set up private access keys.
(Java specific) this also means, in reference to the
Manager functions above, INode will not declare a
public CTOR. java's version of C++ friend class (ITree)
In your case.(look up class access key/Java). This also
Exhibits properties of the Singleton Pattern.
---STOP HERE. This, while appearing quite incomplete, is the
First stage Implementation of the abstract INode
Hierarchy.
This is enough for a Binary Tree Data Structure.
(extend or implement) the INode Interface for
a concrete Binary Tree Node class. So far so simple.
Next, we are looking for the design provisions that will satisfy
a BST Node class. It is conceivable, though neither convenient nor
proper, to implement our current INode Interface as a
Binary Search Tree Node class.(no...no...no...modifications!!)it is what
it is...'Closed for Modifcation && Open for Extension;
We will Extend INode from our new Interface...I think I will call it IOrderedNode Interfaces should always have hyper descriptive
naming conventions. (I know, what happened to mine). Actually, it
does reflect the primary difference between a Binary Tree, and a
Binary Search Tree. A Binary Search Tree is simply an Ordered
Binary Tree. There are implications related to this, apparently
trivial, difference. Mainly, all of the practicality of having a
Serial Data Structure. This means, that we should go back to INode
and evaluate (NOT CHANGE!!) the private Data member.
--------
Hopefully, we were thoughtful when considering the abstract extensibility
of that Data member. If I remember right, generics in java have been
augmented in versatility...I will leave that to you. To borrow a concept
from C++, I would have used a generic pointer to type of template Arg. Or
better yet a void pointer(can't use the asterisk there 'cause it formats my text) doesn't get more abstract than that! the(void)(star), I mean;
Forget for a moment that you are using java, because all types in java are
integral types, via the hash code inherited from the Object class's
ToString() method. User Defined Types (UDTs) should be well thought out
here, because of the disparate implementations across Data Structures that
will implement the series of IFace extensions. (pointers, refs: in java) are always the best initial types at the base levels. They can be
adapted to point to, or hold reference to even the most complex UDT.
Ok, back those Serial attributes we were about to exploit.
Traversals::Pre-Order, In-Order, Post-Order, Breadth-First. Since we are only exploring the INode hierarchy,
we should start considering the algorithms that will be implemented in
the associated Data Structures, and try to identify any subordinate
dependencies that will need to appear in our IOrderedNode
//I think from here on out I will just write the code...
//20 min later...this stupid #$$ message box is the worst
//dev environment I have EVER! worked in...
//......(granted it isn't that)
//40 min later in Visual Studio. Tired of working without
//a net...no KB short cts...NO TAB! no auto formatting...?
template<class T>
class IcanOnlyBeaBT;//fwd _decl
//or a doubley linked list, an Adapter, a...
//keep thinking as you go...
template<class T>
class INode
{
friend class IcanOnlyBeaBT<T>;//this takes care of access
public:
// At this level we have protected
// access for derived classes--
// EXCEPT! with TEMPLATED classes!
// in C++ this is NOT an issue WHEN.
// 1. data members are 'captured' by
// template instantiation
// 2. and 3. are the exact same answer
// as 1. only I would be forced to
// elaborate on two specific instances
// with the only advantage being a
// sufficing ward on those nit-pickers
// who love to leave comments like
//
// "Weellll...NOT exactly"
//
// I dont care. I would rather
// write my explaination for not
// explaining further...
/************************************/
// (no worries here in java - C#)
// implement now to enforce the
// design on higher level abstractions;
// protected access may become
// private in remote derived classes
// we never want to come back here!!!
// push dependencies up! up! up!
INode() : whatever_Data_I_want_Ha_Ha(nullptr) {}
virtual void SetWhatEverDataIWant(T*) = 0;
virtual T* GetWhateverDataIWant() = 0;
virtual T* GetWhateverDataIWant() const = 0;
protected:
virtual ~INode() = 0;
T* whatever_Data_I_want_Ha_Ha;
INode<T>*left_child;
INode<T>*right_child;
};
template<class T>
INode<T>::~INode() {} // don't worry about this it's cool
//...notice that
// the member is protected...and pure virtual...
// it's just a boomerang--
// Notice how adaptable this Interface has become
// after only one extension and implementation is refined.
// This is BOTTOM UP because we are BUILDING...
// ...this should be TOP DOWN as we DESIGN...
// THINK--TOP DOWN...BUILD BOTTOM UP...
// Push ALL negotiable DEPENDENCIES UP AS YOU BUILD.
// Ideally, these were identified during design.
// It rarely ever goes that way cleanly...
// at least not for me, but try...try
// As incremental implementation progresses, You
// may start to identify some of these negotiable
// dependencies...these two interfaces are still
// super lean..and rather boring, but continue towards
// the AVL, Red Black, Other Data structurs they will show.
// Nodes are, for the most part, like a drawer full
// of silverware. They CAN'T do anything unless
// they are being used.
// GO UP now!!!...BUT always JUST enough!!
// No more; GOAL...to have a DESIGN SPECIFIC
// hierarchy, that IS extensible in a MODULAR
// fasion, like LEGOS. ADAPTABLE to ANY COMPATIBLE
// Data Structure, Not just TREES. Even from here...
// there are other suitablilities coming to mind,
// such as Graphs, Doubley Linked Lists, circular queues.
// Nodes are common place in Data Structures...on...on...
// Principle Attribute: ICanBe_A_BST Data Struct now.
// fwd _decl:
template<class T>
class ICanBe_A_BST; //The BT Node was FIRST Abstraction,
// BST is SECOND.
// OR a Composite Object Structure! for the
// Composite Design Pattern...or...or...or
// BECAUSE, this IOrderedNode is more QUALIFIED
// and adaptable. LOOK HERE! Don't throw away
// the specific sutibility of lower abstractions
// This should be extended to fulfil design reqs
// IOrderedNode is not intended to be a BT,
// IT 'IS A' BT by extension, BUT, it is a BST Node.
// This abstract hierarchy, UPON DESIGN COMPLETION
// Will have pervasive extensibility # unique levels.
// think {OPEN-CLOSED} open for EXTENSION, and
// CLOSED for MODIFICATION...GOAL...DON'T...come
// BACK inside this BLACK BOX once it is CLOSED..!
template<class T>
class IOrderedNode : public INode<T>
{
// RIGHT HERE! ALL previous implementation
// Is abstracted AWAY. Look how clean it all is..
// in java you would be Extending INode Interface HERE!.
// Extending IN JAVA IS inheritance.
// ALL public and protected members.
// Closed for MOD. open for EXTENSION
public:
IOrderedNode() : height(0) { }
protected:
//NOTICE!(I Can Be A BST Node IF!)my data is INTEGRAL & comparable.
//FOR instance a bool is unqualified--how can you order a tree
//when the only value is a 1 or a 0;
//UDT is dependent upon guess...
//THE USER who defind it(integral && comparable);
// Question: is there anything missing from this level
// that would disqualify concrete instantiations from adequately
// filling the intended role? .....Seriously...
// I have been awake for two days now. This may need editing.
// Regardless the process is the
// same all the way to Red Black and beyond...
int height; //new data member; height of the tree at that node...
//this comes in handy when computing the balance factor
//on balanced trees...AVL, R&B,
};
/***********************NOTE:***********************
*
* There are several considerations that have to be made
* when you are "leaving" data and and implementation "behind".
* We know we don't EVER want to come back here...
(not a super realistic GOAL...)
* Is the implementation specific to the level of bstraction.?...
* YES? then leave it here.
IS...the DATA specific to the implementation ????
* this deserves 4 Q-marks because, IF at all POSSIBLE PUSH
* these IMPLEMENTATION DEPENDENCIES..UP This RESULTS in IoC
* Inversion of Control Inversion of CONTROL INVERSION! of Control...
* Implementation dependencies should come from higher level abs
* to lower level Implementation...repeats you are seeing all over
this now TLDR, are Cardinal principles of Object
* Oriented Design. Not because I love commenting code...
but since YOU asked...I won't leave out the 'life blood'.
* Incidentally, there is a requisite
'AHAAH moment' that either comes
* or it doesn't.
*
**************************** PERSONAL NOTE:*********************
*
* I picked up java in the late 90's, and was like.
* "...what the hell is an OBJECT..?" Two years of programming from a
* procedural paradigm, in an OOP language-LATER! It hit me......
* (I know...slow learner)...but I remember saying out loud....
* 'THAT...IS...THE...COOLEST...THING...I HAVE EVER...tripped over...
* Consensually, OOP is considered to be in its INFANCY.
* Theories (opinions) are often the cause of some rather heated
* contest. In fact, one of the most intense and persistant
"cival-war" I have ever encountered, nearly dominated an entire
forum. I didn't really know enough to have an opinion
* one way or the other on the matter, but I remember thinking,
how absurd...and laughing alot.
* The theoretical epicenter was localized on the issue of...
wait for it...
*
* INHERITANCE v.s. COMPOSITION/AGGRAGATION
*
* Hmm....Everybody knows that programming to interfaces,
adhereing to common sense, established design principles,
and proven patterns, can all be accomplished without inheriting
from a single archtype...
* "Not that there's anything wrong with that..."
I'm pretty sure, that was the vein of the row on that
forum...Super entertaining though...
*
*******************************************/
I had same problem and decided to go with this simple solution.
abstract class BSTnode<K, M> {
K key;
M meta;
BSTnode<K> left;
BSTnode<K> right;
BSTnode<K> parent;
}
This simply solves the problem for your metadata.
Say I have a List of object which were defined using lambda expressions (closures). Is there a way to inspect them so they can be compared?
The code I am most interested in is
List<Strategy> strategies = getStrategies();
Strategy a = (Strategy) this::a;
if (strategies.contains(a)) { // ...
The full code is
import java.util.Arrays;
import java.util.List;
public class ClosureEqualsMain {
interface Strategy {
void invoke(/*args*/);
default boolean equals(Object o) { // doesn't compile
return Closures.equals(this, o);
}
}
public void a() { }
public void b() { }
public void c() { }
public List<Strategy> getStrategies() {
return Arrays.asList(this::a, this::b, this::c);
}
private void testStrategies() {
List<Strategy> strategies = getStrategies();
System.out.println(strategies);
Strategy a = (Strategy) this::a;
// prints false
System.out.println("strategies.contains(this::a) is " + strategies.contains(a));
}
public static void main(String... ignored) {
new ClosureEqualsMain().testStrategies();
}
enum Closures {;
public static <Closure> boolean equals(Closure c1, Closure c2) {
// This doesn't compare the contents
// like others immutables e.g. String
return c1.equals(c2);
}
public static <Closure> int hashCode(Closure c) {
return // a hashCode which can detect duplicates for a Set<Strategy>
}
public static <Closure> String asString(Closure c) {
return // something better than Object.toString();
}
}
public String toString() {
return "my-ClosureEqualsMain";
}
}
It would appear the only solution is to define each lambda as a field and only use those fields. If you want to print out the method called, you are better off using Method. Is there a better way with lambda expressions?
Also, is it possible to print a lambda and get something human readable? If you print this::a instead of
ClosureEqualsMain$$Lambda$1/821270929#3f99bd52
get something like
ClosureEqualsMain.a()
or even use this.toString and the method.
my-ClosureEqualsMain.a();
This question could be interpreted relative to the specification or the implementation. Obviously, implementations could change, but you might be willing to rewrite your code when that happens, so I'll answer at both.
It also depends on what you want to do. Are you looking to optimize, or are you looking for ironclad guarantees that two instances are (or are not) the same function? (If the latter, you're going to find yourself at odds with computational physics, in that even problems as simple as asking whether two functions compute the same thing are undecidable.)
From a specification perspective, the language spec promises only that the result of evaluating (not invoking) a lambda expression is an instance of a class implementing the target functional interface. It makes no promises about the identity, or degree of aliasing, of the result. This is by design, to give implementations maximal flexibility to offer better performance (this is how lambdas can be faster than inner classes; we're not tied to the "must create unique instance" constraint that inner classes are.)
So basically, the spec doesn't give you much, except obviously that two lambdas that are reference-equal (==) are going to compute the same function.
From an implementation perspective, you can conclude a little more. There is (currently, may change) a 1:1 relationship between the synthetic classes that implement lambdas, and the capture sites in the program. So two separate bits of code that capture "x -> x + 1" may well be mapped to different classes. But if you evaluate the same lambda at the same capture site, and that lambda is non-capturing, you get the same instance, which can be compared with reference equality.
If your lambdas are serializable, they'll give up their state more easily, in exchange for sacrificing some performance and security (no free lunch.)
One area where it might be practical to tweak the definition of equality is with method references because this would enable them to be used as listeners and be properly unregistered. This is under consideration.
I think what you're trying to get to is: if two lambdas are converted to the same functional interface, are represented by the same behavior function, and have identical captured args, they're the same
Unfortunately, this is both hard to do (for non-serializable lambdas, you can't get at all the components of that) and not enough (because two separately compiled files could convert the same lambda to the same functional interface type, and you wouldn't be able to tell.)
The EG discussed whether to expose enough information to be able to make these judgments, as well as discussing whether lambdas should implement more selective equals/hashCode or more descriptive toString. The conclusion was that we were not willing to pay anything in performance cost to make this information available to the caller (bad tradeoff, punishing 99.99% of users for something that benefits .01%).
A definitive conclusion on toString was not reached but left open to be revisited in the future. However, there were some good arguments made on both sides on this issue; this is not a slam-dunk.
To compare labmdas I usually let the interface extend Serializable and then compare the serialized bytes. Not very nice but works for the most cases.
I don't see a possibility, to get those informations from the closure itself.
The closures doesn't provide state.
But you can use Java-Reflection, if you want to inspect and compare the methods.
Of course that is not a very beautiful solution, because of the performance and the exceptions, which are to catch. But this way you get those meta-informations.
In the interests of helping to understand what a monad is, can someone provide an example using java ? Are they possible ?
Lambda expressions are possible using java if you download the pre-release lambda compatible JDK8 from here http://jdk8.java.net/lambda/
An example of a lambda using this JDK is shown below, can someone provide a comparably simple monad ?
public interface TransformService {
int[] transform(List<Integer> inputs);
}
public static void main(String ars[]) {
TransformService transformService = (inputs) -> {
int[] ints = new int[inputs.size()];
int i = 0;
for (Integer element : inputs) {
ints[i] = element;
}
return ints;
};
List<Integer> inputs = new ArrayList<Integer>(5) {{
add(10);
add(10);
}};
int[] results = transformService.transform(inputs);
}
Just FYI:
The proposed JDK8 Optional class does satisfy the three Monad laws. Here's a gist demonstrating that.
All it takes be a Monad is to provide two functions which conform to three laws.
The two functions:
Place a value into monadic context
Haskell's Maybe: return / Just
Scala's Option: Some
Functional Java's Option: Option.some
JDK8's Optional: Optional.of
Apply a function in monadic context
Haskell's Maybe: >>= (aka bind)
Scala's Option: flatMap
Functional Java's Option: flatMap
JDK8's Optional: flatMap
Please see the above gist for a java demonstration of the three laws.
NOTE: One of the key things to understand is the signature of the function to apply in monadic context: it takes the raw value type, and returns the monadic type.
In other words, if you have an instance of Optional<Integer>, the functions you can pass to its flatMap method will have the signature (Integer) -> Optional<U>, where U is a value type which does not have to be Integer, for example String:
Optional<Integer> maybeInteger = Optional.of(1);
// Function that takes Integer and returns Optional<Integer>
Optional<Integer> maybePlusOne = maybeInteger.flatMap(n -> Optional.of(n + 1));
// Function that takes Integer and returns Optional<String>
Optional<String> maybeString = maybePlusOne.flatMap(n -> Optional.of(n.toString));
You don't need any sort of Monad Interface to code this way, or to think this way. In Scala, you don't code to a Monad Interface (unless you are using Scalaz library...). It appears that JDK8 will empower Java folks to use this style of chained monadic computations as well.
Hope this is helpful!
Update: Blogged about this here.
Java 8 will have lambdas; monads are a whole different story. They are hard enough to explain in functional programming (as evidenced by the large number of tutorials on the subject in Haskell and Scala).
Monads are a typical feature of statically typed functional languages. To describe them in OO-speak, you could imagine a Monad interface. Classes that implement Monad would then be called 'monadic', provided that in implementing Monad the implementation obeys what are known as the 'monad laws'. The language then provides some syntactic sugar that makes working with instances of the Monad class interesting.
Now Iterable in Java has nothing to do with monads, but as a example of a type that the Java compiler treats specially (the foreach syntax that came with Java 5), consider this:
Iterable<Something> things = getThings(..);
for (Something s: things) { /* do something with s */ }
So while we could have used Iterable's Iterator methods (hasNext and company) in an old-style for loop, Java grants us this syntactic sugar as a special case.
So just as classes that implement Iterable and Iterator must obey the Iterator laws (Example: hasNext must return false if there is no next element) to be useful in foreach syntax - there would exist several monadic classes that would be useful with a corresponding do notation (as it is called in Haskell) or Scala's for notation.
So -
What are good examples of monadic classes?
What would syntactic sugar for dealing with them look like?
In Java 8, I don't know - I am aware of the lambda notation but I am not aware of other special syntactic sugar, so I'll have to give you an example in another language.
Monads often serve as container classes (Lists are an example). Java already has java.util.List which is obviously not monadic, but here is Scala's:
val nums = List(1, 2, 3, 4)
val strs = List("hello", "hola")
val result = for { // Iterate both lists, return a resulting list that contains
// pairs of (Int, String) s.t the string size is same as the num.
n <- nums
s <- strs if n == s.length
} yield (n, s)
// result will be List((4, "hola"))
// A list of exactly one element, the pair (4, "hola")
Which is (roughly) syntactic sugar for:
val nums = List(1, 2, 3, 4)
val strs = List("hello", "hola")
val results =
nums.flatMap( n =>
strs.filter(s => s.size == n). // same as the 'if'
map(s => (n, s)) // Same as the 'yield'
)
// flatMap takes a lambda as an argument, as do filter and map
//
This shows a feature of Scala where monads are exploited to provide list comprehensions.
So a List in Scala is a monad, because it obeys Scala's monad laws, which stipulate that all monad implementations must have conforming flatMap, map and filter methods (if you are interested in the laws, the "Monads are Elephants" blog entry has the best description I've found so far). And, as you can see, lambdas (and HoF) are absolutely necessary but not sufficient to make this kind of thing useful in a practical way.
There's a bunch of useful monads besides the container-ish ones as well. They have all kinds of applications. My favorite must be the Option monad in Scala (the Maybe monad in Haskell), which is a wrapper type which brings about null safety: the Scala API page for the Option monad has a very simple example usage: http://www.scala-lang.org/api/current/scala/Option.html
In Haskell, monads are useful in representing IO, as a way of working around the fact that non-monadic Haskell code has indeterminate order of execution.
Having lambdas is a first small step into the functional programming world; monads
require both the monad convention and a large enough set of usable monadic types, as well as syntactic sugar to make working with them fun and useful.
Since Scala is arguably the language closest to Java that also allows (monadic) Functional Programming, do look at this Monad tutorial for Scala if you are (still) interested:
http://james-iry.blogspot.jp/2007/09/monads-are-elephants-part-1.html
A cursory googling shows that there is at least one attempt to do this in Java: https://github.com/RichardWarburton/Monads-in-Java -
Sadly, explaining monads in Java (even with lambdas) is as hard as explaining full-blown Object oriented programming in ANSI C (instead of C++ or Java).
Even though monads can be implemented in Java, any computation involving them is doomed to become a messy mix of generics and curly braces.
I'd say that Java is definitely not the language to use in order to illustrate their working or to study their meaning and essence. For this purpose it is far better to use JavaScript or to pay some extra price and learn Haskell.
Anyway, I am signaling you that I just implemented a state monad using the new Java 8 lambdas. It's definitely a pet project, but it works on a non-trivial test case.
You may find it presented at my blog, but I'll give you some details here.
A state monad is basically a function from a state to a pair (state,content). You usually give the state a generic type S and the content a generic type A.
Because Java does not have pairs we have to model them using a specific class, let's call it Scp (state-content pair), which in this case will have generic type Scp<S,A> and a constructor new Scp<S,A>(S state,A content). After doing that we can say that the monadic function will have type
java.util.function.Function<S,Scp<S,A>>
which is a #FunctionalInterface. That's to say that its one and only implementation method can be invoked without naming it, passing a lambda expression with the right type.
The class StateMonad<S,A> is mainly a wrapper around the function. Its constructor may be invoked e.g. with
new StateMonad<Integer, String>(n -> new Scp<Integer, String>(n + 1, "value"));
The state monad stores the function as an instance variable. It is then necessary to provide a public method to access it and feed it the state. I decided to call it s2scp ("state to state-content pair").
To complete the definition of the monad you have to provide a unit (aka return) and a bind (aka flatMap) method. Personally I prefer to specify unit as static, whereas bind is an instance member.
In the case of the state monad, unit gotta be the following:
public static <S, A> StateMonad<S, A> unit(A a) {
return new StateMonad<S, A>((S s) -> new Scp<S, A>(s, a));
}
while bind (as instance member) is:
public <B> StateMonad<S, B> bind(final Function<A, StateMonad<S, B>> famb) {
return new StateMonad<S, B>((S s) -> {
Scp<S, A> currentPair = this.s2scp(s);
return famb(currentPair.content).s2scp(currentPair.state);
});
}
You notice that bind must introduce a generic type B, because it is the mechanism that allows the chaining of heterogeneous state monads and gives this and any other monad the remarkable capability to move the computation from type to type.
I'd stop here with the Java code. The complex stuff is in the GitHub project. Compared to previous Java versions, lambdas remove a lot of curly braces, but the syntax is still pretty convoluted.
Just as an aside, I'm showing how similar state monad code may be written in other mainstream languages. In the case of Scala, bind (which in that case must be called flatMap) reads like
def flatMap[A, B](famb: A => State[S, B]) = new State[S, B]((s: S) => {
val (ss: S, aa: A) = this.s2scp(s)
famb(aa).s2scp(ss)
})
whereas the bind in JavaScript is my favorite; 100% functional, lean and mean but -of course- typeless:
var bind = function(famb){
return state(function(s) {
var a = this(s);
return famb(a.value)(a.state);
});
};
<shameless>
I am cutting a few corners here, but if you are interested in the details you will find them on my WP blog.</shameless>
Here's the thing about monads which is hard to grasp: monads are a
pattern, not a specific type. Monads are a shape, they are an abstract
interface (not in the Java sense) more than they are a concrete data
structure. As a result, any example-driven tutorial is doomed to
incompleteness and failure.
[...]
The only way to understand monads is to see them for what they are: a mathematical construct.
Monads are not metaphors by Daniel Spiewak
Monads in Java SE 8
List monad
interface Person {
List<Person> parents();
default List<Person> greatGrandParents1() {
List<Person> list = new ArrayList<>();
for (Person p : parents()) {
for (Person gp : p.parents()) {
for (Person ggp : p.parents()) {
list.add(ggp);
}
}
}
return list;
}
// <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
default List<Person> greatGrandParents2() {
return Stream.of(parents())
.flatMap(p -> Stream.of(p.parents()))
.flatMap(gp -> Stream.of(gp.parents()))
.collect(toList());
}
}
Maybe monad
interface Person {
String firstName();
String middleName();
String lastName();
default String fullName1() {
String fName = firstName();
if (fName != null) {
String mName = middleName();
if (mName != null) {
String lName = lastName();
if (lName != null) {
return fName + " " + mName + " " + lName;
}
}
}
return null;
}
// <U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
default Optional<String> fullName2() {
return Optional.ofNullable(firstName())
.flatMap(fName -> Optional.ofNullable(middleName())
.flatMap(mName -> Optional.ofNullable(lastName())
.flatMap(lName -> Optional.of(fName + " " + mName + " " + lName))));
}
}
Monad is a generic pattern for nested control flow encapsulation.
I.e. a way to create reusable components from nested imperative idioms.
Important to understand that a monad is not just a generic wrapper class with a flat map operation.
For example, ArrayList with a flatMap method won't be a monad.
Because monad laws prohibit side effects.
Monad is a formalism. It describes the structure, regardless of content or meaning.
People struggle with relating to meaningless (abstract) things.
So they come up with metaphors which are not monads.
See also:
conversation between Erik Meijer and Gilad Bracha.
the only way to understand monads is by writing a bunch of combinator libraries, noticing the resulting duplication, and then discovering for yourself that monads let you factor out this duplication. In discovering this, everyone builds some intuition for what a monad is… but this intuition isn’t the sort of thing that you can communicate to someone else directly – it seems everyone has to go through the same experience of generalizing to monads from some concrete examples of combinator libraries. however
here i found some materials to learn Mondas.
hope to be useful for you too.
codecommit
james-iry.blogspot
debasishg.blogspot
This blog post gives a step-by-step example of how you might implement a Monad type (interface) in Java and then use it to define the Maybe monad, as a practical application.
This post explains that there is one monad built into the Java language, emphasising the point that monads are more common than many programmers may think and that coders often inadvertently reinvent them.
Despite all controversy about Optional satisfying, or not, the Monad laws, I usually like to look at Stream, Optional and CompletableFuture in the same way. In truth, all them provide a flatMap() and that is all I care and let me embrace the "the tasteful composition of side effects" (cited by Erik Meijer). So we may have corresponding Stream, Optional and CompletableFuture in the following way:
Regarding Monads, I usually simplify it only thinking on flatMap()(from "Principles of Reactive Programming" course by Erik Meijer):
A diagram for the "Optional" Monad in Java.
Your task: Perform operations on the "Actuals" (left side) transforming elements of type T union null to type U union null using the function in the light blue box (the light blue box function). Just one box is shown here, but there may be a chain of the light blue boxes (thus proceeding from type U union null to type V _union null to type W union null etc.)
Practically, this will cause you to worry about null values appearing in the function application chain. Ugly!
Solution: Wrap your T into an Optional<T> using the light green box functions, moving to the "Optionals" (right side). Here, transform elements of type Optional<T> to type Optional<U> using the red box function. Mirroring the application of functions to the "Actuals", there may be several red box functions to be be chained (thus proceeding from type Optional<U> to Optional<V> then to Optional<W> etc.). In the end, move back from the "Optionals" to the "Actuals" through one of the dark green box functions.
No worrying about null values anymore. Implementationwise, there will always be an Optional<U>, which may or may not be empty. You can chain the calls to to the red box functions without null checks.
The key point: The red box functions are not implemented individually and directly. Instead, they are obtained from the blue box functions (whichever have been implemented and are available, generally the light blue ones) by using either the map or the flatMap higher-order functions.
The grey boxes provide additional support functionality.
Simples.
I like to think of monads in slighlty more mathematical (but still informal) fashion. After that I will explain the relationship to one of Java 8's monads CompletableFuture.
First of all, a monad M is a functor. That is, it transforms a type into another type: If X is a type (e.g. String) then we have another type M<X> (e.g. List<String>). Moreover, if we have a transformation/function X -> Y of types, we should get a function M<X> -> M<Y>.
But there is more data to such a monad. We have a so-called unit which is a function X -> M<X> for each type X. In other words, each object of X can be wrapped in a natural way into the monad.
The most characteristic data of a monad, however, is it's product: a function M<M<X>> -> M<X> for each type X.
All of these data should satisfy some axioms like functoriality, associativity, unit laws, but I won't go into detail here and it also doesn't matter for practical usage.
We can now deduce another operation for monads, which is often used as an equivalent definition for monads, the binding operation: A value/object in M<X> can be bound with a function X -> M<Y> to yield another value in M<Y>. How do we achieve this? Well, first we apply functoriality to the function to obtain a function M<X> -> M<M<Y>>. Next we apply the monadic product to the target to obtain a function M<X> -> M<Y>. Now we can plug in the value of M<X> to obtain a value in M<Y> as desired. This binding operation is used to chain several monadic operations together.
Now lets come to the CompletableFuture example, i.e. CompletableFuture = M. Think of an object of CompletableFuture<MyData> as some computation that's performed asynchronously and which yields an object of MyData as a result some time in the future. What are the monadic operations here?
functoriality is realized with the method thenApply: first the computation is performed and as soon as the result is available, the function which is given to thenApply is applied to transform the result into another type
the monadic unit is realized with the method completedFuture: as the documentation tells, the resulting computation is already finished and yields the given value at once
the monadic product is not realized by a function, but the binding operation below is equivalent to it (together with functoriality) and its semantic meaning is simply the following: given a computation of type CompletableFuture<CompletableFuture<MyData>> that computation asynchronously yields another computation in CompletableFuture<MyData> which in turn yields some value in MyData later on, so performing both computations on after the other yields one computation in total
the resulting binding operation is realized by the method thenCompose
As you see, computations can now be wrapped up in a special context, namely asynchronicity. The general monadic structures enable us to chain such computations in the given context. CompletableFuture is for example used in the Lagom framework to easily construct highly asynchronous request handlers which are transparently backed up by efficient thread pools (instead of handling each request by a dedicated thread).
Haskell monads is an interface which specify rules to convert “datatype that is wrapped in another datatype” to another “datatype that is wrapped in another or same datatype”; the conversion steps is specified by a function you define with a format.
The function format takes a datatype and return “datatype that is wrapped in another datatype”. You can specify operations/ calculations during conversion e.g. multiply or lookup something.
It is so difficult to understand because of the nested abstraction. It is so abstracted so that you can reuse the rules to convert datatype in a datatype without custom programming to unwrap the first “ datatype that is wrapped in another datatype” before putting the data to your specified function; Optional with some datatype is an example of “datatype in a datatype”.
The specified function is any lambda confirming the format.
You don’t need to fully understand it; you will write your own reusable interface to solve similar problem. Monad is just exist because some mathematicians already hit and resolve that problem, and create monad for you to reuse. But due to its abstraction, it is difficult to learn and reuse in the first place.
In other words, e.g. Optional is a wrapper class, but some data is wrapped , some not, some function take wrapped data type but some don’t, return type can be of type wrapped or not. To chain calling mixture of function which may wrap or not in parameter/return types, you either do your own custom wrap/unwrap or reuse pattern of functor / applicative / monad to deal with all those wrapped/unwrapped combinations of chained function call. Every time u try to put optional to a method that only accept plain value and return optional, the steps are what monad does.
Java programmers and API seems to favor explicit set/get methods.
however I got the impression C++ community frowns upon such practice.
If it is so,is there a particular reason (besides more lines of code) why this is so?
on the other hand, why does Java community choose to use methods rather than direct access?
Thank you
A well designed class should ideally not have too many gets and sets. In my opinion, too many gets and sets are basically an indication of the fact that someone else (and potentially many of them) need my data to achieve their purpose. In that case, why does that data belong to me in the first place? This violates the basic principle of encapsulation (data + operations in one logical unit).
So, while there is no technical restriction and (in fact abundance of) 'set' and 'get' methods, I would say that you should pause and reinspect your design if you want too many of those 'get' and 'set' in your class interface used by too many other entities in your system.
There are occasions when getters/setters are appropriate but an abundance of getters/setters typically indicate that your design fails to achieve any higher level of abstraction.
Typically it's better (in regards to encapsulation) to exhibit higher level operations for your objects that does not make the implementation obvious to the user.
Some other possible reasons why it's not as common in C++ as in Java:
The Standard Library does not use it.
Bjarne Stroustrup expresses his dislike towards it (last paragraph):
I particularly dislike classes with a
lot of get and set functions. That is
often an indication that it shouldn't
have been a class in the first place.
It's just a data structure. And if it
really is a data structure, make it a
data structure.
The usual argument against get/set methods is that if you have both and they're just trivial return x; and x = y; then you haven't actually encapsulated anything at all; you may as well just make the member public which saves a whole lot of boilerplate code.
Obviously there are cases where they still make sense; if you need to do something special in them, or you need to use inheritance or, particularly, interfaces.
There is the advantage that if you implement getters/setters you can change their implementation later without having to alter code that uses them. I suppose the frowning on it you refer to is kind of a YAGNI thing that if there's no expectation of ever altering the functions that way, then there's little benefit to having them. In many cases you can just deal with the case of altering the implementation later anyway.
I wasn't aware that the C++ community frowned on them any more or less than the Java community; my impression is that they're rather less common in languages like Python, for example.
I think the reason the C++ community frowns on getters and setters is that C++ offers far better alternatives. For example:
template <class T>
class DefaultPredicate
{
public:
static bool CheckSetter (T value)
{
return true;
}
static void CheckGetter (T value)
{
}
};
template <class T, class Predicate = DefaultPredicate <T>>
class Property
{
public:
operator T ()
{
Predicate::CheckGetter (m_storage);
return m_storage;
}
Property <T, Predicate> &operator = (T rhs)
{
if (Predicate::CheckSetter (rhs))
{
m_storage = rhs;
}
return *this;
}
private:
T m_storage;
};
which can then be used like this:
class Test
{
public:
Property <int> TestData;
Property <int> MoreTestData;
};
int main ()
{
Test
test;
test.TestData = 42;
test.MoreTestData = 24;
int value = test.TestData;
bool check = test.TestData == test.MoreTestData;
}
Notice that I added a predicate parameter to the property class. With this, we can get creative, for example, a property to hold an integer colour channel value:
class NoErrorHandler
{
public:
static void SignalError (const char *const error)
{
}
};
class LogError
{
public:
static void SignalError (const char *const error)
{
std::cout << error << std::endl;
}
};
class Exception
{
public:
Exception (const char *const message) :
m_message (message)
{
}
operator const char *const ()
{
return m_message;
}
private:
const char
*const m_message;
};
class ThrowError
{
public:
static void SignalError (const char *const error)
{
throw new Exception (error);
}
};
template <class ErrorHandler = NoErrorHandler>
class RGBValuePredicate : public DefaultPredicate <int>
{
public:
static bool CheckSetter (int rhs)
{
bool
setter_ok = true;
if (rhs < 0 || rhs > 255)
{
ErrorHandler::SignalError ("RGB value out of range.");
setter_ok = false;
}
return setter_ok;
}
};
and it can be used like this:
class Test
{
public:
Property <int, RGBValuePredicate <> > RGBValue1;
Property <int, RGBValuePredicate <LogError> > RGBValue2;
Property <int, RGBValuePredicate <ThrowError> > RGBValue3;
};
int main ()
{
Test
test;
try
{
test.RGBValue1 = 4;
test.RGBValue2 = 5;
test.RGBValue3 = 6;
test.RGBValue1 = 400;
test.RGBValue2 = 500;
test.RGBValue3 = -6;
}
catch (Exception *error)
{
std::cout << "Exception: " << *error << std::endl;
}
}
Notice that I made the handling of bad values a template parameter as well.
Using this as a starting point, it can be extended in many different ways.
For example, allow the storage of the property to be different to the public type of the value - so the RGBValue above could use an unsigned char for storage but an int interface.
Another example is to change the predicate so that it can alter the setter value. In the RGBValue above this could be used to clamp values to the range 0 to 255 rather than generate an error.
Properties as a general language concept technically predate C++, e.g. in Smalltalk, but they weren't ever part of the standard. Getters and setters were a concept used in C++ when it was used for development of UI's, but truth be told, it's an expensive proposition to develop UI's in what is effectively a systems language. The general problem with getters and setters in C++ was that, since they weren't a standard, everybody had a different standard.
And in systems languages, where efficiency concerns are high, then it's just easier to make the variable itself public, although there's a lot of literature that frowns mightily on that practice. Often, you simply see richer exchanges of information between C++ object instances than simple items.
You'll probably get a lot of viewpoints in response to this question, but in general, C++ was meant to be C that did objects, making OOP accessable to developers that didn't know objects. It was hard enough to get virtuals and templates into the language, and I think that it's been kind of stagnant for a while.
Java differs because in the beginning, with what Java brought in areas like garbage collection, it was easier to promote the philosophy of robust encapsulation, i.e. external entities should keep their grubby little paws off of internal elements of a class.
I admit this is pretty much opinion - at this time I use C++ for highly optimized stuff like 3D graphics pipelines - I already have to manage all my object memory, so I'd take a dim view of fundamentally useless code that just serves to wrap storage access up in additional functions - that said, the basic performance capabilies of runtimes like the MSFT .net ILM make that a position that can be difficult to defend at times
Purely my 2c
There's nothing unusual about having explicit set/get methods in C++. I've seen it in plenty of C++, it can be very useful to not allow direct access to data members.
Check out this question for an explanation of why Java tends to prefer them and the reasons for C++ are the same. In short: it allows you to change the way data members are accessed without forcing client code (code that uses your code) to recompile. It also allows you to enforce a specific policy for how to access data and what to do when that data is accessed.
By mandating the use of set/get methods, one can implement useful side-effects in the getter/setter (for example, when the argument to get/set is an object).
I am surprised nobody has mentioned Java introspection and beans yet.
Using get.../set... naming convention combined with introspection allows all sorts of clever trickery with utility classes.
I personally feel that the "public" keyword should have been enough to trigger the bean magic but I am not Ray Gosling.
My take on this is that in C++ is a rather pointless exercise. You are adding at least six lines of code to test and maintain which perform no purpose and will for the most part be ignored by the compiler. It doesnt really protect your class from misuse and abuse unless you add a lot more coding.
I don't think the C++ community frowned on using getters and setters. They are almost always a good idea.
It has to do with the basics of object oriented programming - hiding the internals of an object from its users. The users of an object should not need to know (nor should they care) about the internals of an object.
It also gives you control over what is done whenever a user of your object tries to read/write to it. In effect, you expose an interface to the object's users. They have to use that interface and you control what happens when methods in that interface are called - the getters and setters would be part of the interface.
It just makes things easier when debugging. A typical scenario is when your object lands up in a weird state and you're debugging to find out how it got there. All you do is set breakpoints in your getters and setters and assuming all else is fine, you're able to see how your object gets to the weird state. If your object's users are all directly accessing its members, figuring out when your object's state changes becomes a lot harder (though not impossible)
I would argue that C++ needs getters/setters more than Java.
In Java, if you start with naked field access, and later you changed your mind, you want getter/setter instead, it is extremely easy to find all the usages of the field, and refactor them into getter/setter.
in C++, this is not that easy. The language is too complex, IDEs simply can't reliably do that.
so In C++, you better get it right the first time. In Java, you can be more adventurous.
There were gets/sets long before java. There are many reasons to use them, especially, if you have to recalculate sth. wenn a value changes. So the first big advantage is, that you can watch to value changes. But imho its bad to ALWAYS implement get and set-often a get is enough. Another point is, that class changes will directly affect your customers. You cant change member names without forcing to refactor the clients code with public members. Lets say, you have an object with a lenght and you change this member name...uh. With a getter, you just change you side of the code and the client can sleep well. Adding gets/Sets for members that should be hidden is of course nonsense.