How to create a Java class with a private final field in Clojure?
ClojureDocs for gen-class say that state field will be public
:state name
If supplied, a public final instance field with the given name will be
created.
So, in other words, do we have a way to create a class and after this a java object with the encapsulated state?
#alexmiller answered on this question recently here
In short, no. As you mention in the docs, gen-class state fields will
be public final fields. However, that field can be (for example), an
atom that is statefully modified by the implementation methods. In
general, we do not give much weight to encapsulation in Clojure -
instead preferring to make things visible, but "safe" (via
immutability). To quote Rich from
https://clojure.org/reference/datatypes, "encapsulation is folly".
gen-class is not a general purpose DSL for generating all possible
Java classes. It is a tool to generate classes in a certain style in
line with Clojure's aesthetics.
Another path however to something along these lines is to use a
deftype, which can have private mutable fields, exposed by
implementing interfaces or protocols inline. The deftype fields can
have meta of either ^:volatile-mutable or ^:unsynchronized-mutable,
both of which will become private fields.
Related
The ClojureScript library Om Next makes use of a static protocols. I have never seen this before and am wondering if it's an Om specific concept, or an actual part of the language. Here is a simplified down code snippet:
(deftype type
static IProtocol
(some-method [this] "val"))
What exactly does this do? (Typing it into a REPL doesn't yield any errors, so I'm led to believe it's not Om specific).
deftype is a low level feature of the language, it's how Clojure is built. At it's core it's just a java Class constructor, it sets fields and methods. A static in java is a keyword that indicates that the methods declared are members of the Class, not of the instance of the Class, thus globally available to instances through inheritance. defui is a macro much like deftype but instead of Classes it's a constructor for javascript Object Prototypes which are analogous. The main difference is that it doesn't take fields just methods. Object Prototypes can be instantiated, so for behavior to be uniformly available to all instances they need to have static fields.
As an example, a string that contains only a valid email address, as defined by some regex.
If a field of this type would be a part of a more complex data structure, or would be used as a function parameter, or used in any other context, the client code would be able to assume the field is a string containing a valid email address. Thus, no checks like "valid?" should be ever necessary, so approach of domaintypes would not work.
In Haskell this could be accomplished by a smart constructor (section 1.2) and in Java by ensuring the type is immutable (all setters private) and by adding a check in the constructor that throws a RuntimeException if the string used to create the type doesn't contain a valid email address.
If this is impossible in plain Clojure, I would like to see an example implementation in some well known extensions of the language, like Typed Clojure.
Ok, maybe, I understand now a question and I formulate in the comment my thoughts not really well. So I try to suggest an admissible solution to your question and then I try to explain some ideas I tried to tell in the comment.
1) There is a gen-class that generates compiled bytecode for a class and you can set constructor for the class there.
2) You can create a record with defrecord in some namespace that is private by convention in your project, then you
create another namespace with public api and define your factory function here. So the user of your public namespace will be able to call only public functions of your public namespace. (Of course, he can call also private ones, but with some another code)
3) You can just define a function like make-email that will return a map.
So you didn't specify your data structure anywhere.
4) You can just document your code where you will warn people to use the factory function for construction.
But! In Java if your code requires some interface, then it's user problem to give to your code the valid interface implementation. So if you write even a little bit general code in Java you already has lost the property of the valid email string. This stuff with interfaces is because Java is statically typed language.
Clojure is, in general, dynamically typed, so the user, in general, should be able to pass arbitrary data structure to arbitrary function without any type problems in compile time and it's his fault if he pass the wrong data. That makes, for example, this thing possible: You create a record and create a factory (constructor) function. And you expect a record to be passed in your code. But the user can pass a map with the same keys as your record fields names and the code will work.
So, in general, if you want the user of your code to be responsible for passing a required typed in dynamically typed language, then it cost nothing for user to be responsible for constructing it in a correct way that you provide to him.
Another solutions are: User just write tests. You can specify in your api functions :pre and :post conditions to check the structure. You can use typed clojure with the ideas I wrote above. And you can use some additional declarative libraries, like that was mentioned in the first comment of #Thumbnail.
P.S. I'm not a clojure professional, so I could easily miss some better solutions.
I am very sorry if this question seems stupid, i am a newbie to TCL and TCLtest, I am trying to perform unit test on a few TCLOO programs, and i am having difficulties testing the private methods ( the methods called using keyword 'my' ). Guidance needed
Leaving aside the question of whether you should test private methods, you can get at the methods by one of these schemes:
Use [info object namespace $inst]::my $methodname to call it, which takes advantage of the fact that you can use introspection to find out the real name of my (and that's guaranteed to work; it's needed for when you're doing callbacks with commands like vwait, trace, and Tk's bind).
Use oo::objdefine $inst export $methodname to make the method public for the particular instance. At that point, you can just do $inst $methodname as normal.
Consequence: You should not use a TclOO object's private methods for things that have to be protected heavily (by contrast with, say, a private field in a Java object). The correct level for handling such shrouding of information is either to put it in a master interpreter (with the untrusted code evaluating in a safe slave) or to keep the protected information at the underlying implementation (i.e., C) level. The best option of those two depends on the details of your program; it's usually pretty obvious which is the right choice (you don't write C just for this if you're otherwise just writing Tcl code).
This might look like OT, but bear with me.
Are you sure you have to test private methods? That sounds like testing the implementantion, and thats something you shouldnt do. You should be testing the behavior of your class, and that is tested through its public methods.
If you have a complicated chunk of code in one of the private methods, and you feel it needs to be tested spearately, consider refactoring the code into two separate classes. Make the method that needs testing public in one of the two classes.
That way you avoid having a "god class" that does everything and you get to test what you wanted to test. You might want to read more about Single Responsibility Principle.
If you need specific book titles on refactoring, id recommend "Clean Code" by Robert C. Martin. I love that book!
I am using bada and refer to the tutorial here, which begins:
class MainForm:
public Osp::Ui::Controls::Form,
public Osp::Ui::IActionEventListener,
public Osp::Ui::ITouchEventListener
{
I am running code where I recently removed the public specifier to cut down on my public API. You'll see that the functions implementing those interfaces where all also declared publicly, for which I saw no need and made private. I would do this without hesitation when implementing my own interfaces when those interfaces may provide more access than I would wish regular clients of my concrete class to receive.
What is the reason for making them public, what am I missing?
I guess it is advocated to aid extensibility, but for a dev making apps not libraries I would challenge this wisdom.
If Form, IActionEventListener and ITouchEventListener already support many usable methods, in most cases why hide them? On the contrary: if you hide them and in the future someone will need them, it will be harder for you to maintain the class because you'll need to provide them again.
If you need to hide the parent's methods, there's another way to do this: instead of inheriting, enclose the "parent" as a field in your new class.
In some languages such as C#, public inheritance is the only option.
For me private inheritance of "interfaces" is a non sens.
The interface of an object is its set of public methods. As llya said, if you want to use the functionalities provided by a class internally, use object composition. If you want to provide a subset of the interface, then either compose or simply declare a more restrictive interface.
If the "interface" and the functions taking object from this interface are in a third party library then its means that the developers wanted to force you to implement every methods, so you have to provide them.
There are a few different ways to create Java classes in Clojure, so what are the tradeoffs when picking between gen-class, proxy, and reify in Clojure? (are there other ways to create Java classes that I haven't listed?)
My basic understanding is that I have listed these constructs in decreasing order of power.
Use gen-class when you want a named class or you want to add new methods to objects you create. gen-class relies on AOT compilation.
When you want an anonymous, one-off implementation of a type you use reify or proxy. They do not rely on AOT compilation. Here are their differences:
reify only supports protocols or interfaces, proxy also supports concrete superclasses.
reify uses true class methods, proxy uses external functions.
Because of #2, reify uses direct method lookup, while proxy uses a map for method lookup.
Because of #3, reify does not support dynamic swapping of methods, but proxy does.
reify will perform better than proxy, so you should always use reify when possible. Only use proxy when reify's constraints are too prohibitive.
In addition to gen-class, proxy and reify, we have defrecord and deftype. These latter two options should be your first choices for the creation of named java classes (and in the case of defrecord, your first choice for any kind of struct with named components.)
The datatypes page on clojure.org is a good reference on this topic. Defrecord, deftype and reify are newer than gen-class and proxy, having been introduced in version 1.2 (I think -- possibly 1.1). Defrecord and deftype both create classes that conform to interfaces, but do not allow for inheritance. If you need inheritance, gen-class (and proxy for anonymous classes) is still your only option.
Defrecord and deftype differ in what you are given for free. Defrecord automatically creates a class which conforms to IPersistentMap and ISeq. Deftype, on the other hand, gives you more control over your class, even allowing for mutable fields (not allowed in defrecord). In general, deftype is intended for low-level implementation of data structures, whereas defrecord is intended for most day-to-day use.