Say I have bunch of Scala classes and I want to compile and package it to JAR.
I want to expose only some limited number of classes to external user of the JAR and "hide" any other classes.
The question: How can I achieve that without explicitly specifying private access modifier for classes to hide?
The problem is that in Scala class is public by default.
The ideal solution would be some Scala compiler option that changes default class modifier to private.
I think you answered your own question. Scala provides private for exactly this usecase.
Related
I am currently reading "Scala Programming, 2nd ed." (OReilly 2015) by Wampler/Payne, and they mention Package Objects as a means to expose abstractions.
On p.504 however, they mention
Package objects
An alternative to finegrained visibility controls is putting all implementation constructs in a protected package, then using a top-level package object to expose only the appropriate public abstractions. For example, type members can alias types that would otherwise be hidden [...]"
Now my question is: is there a way to declare said protected package as protected once, without having to declare it for every every class/object down the hierarchy? And if so, how?
Or did I simply misunderstand the authors?
As clarification: I am currently working on a library which is supposed to expose minimal API in order for $colleagues to have to actually touch internals to make fundamental changes or to have to do configuration via config-files.
Second question: is this the right path to go? Should I maybe go another route?
Doing a little research of my own, it seems to me that it's not possible in Scala to declare a package to be entirely private. (You can check out the Language Specification here, where there is no mention of being able to qualify a package declaration with 'private' or similar)
I think what the authors are suggesting is the following, roughly translated:
Instead of using finegrained controls, such as declaring some of your class members private or protected and leaving the rest public, you could make all of the important classes in your package completely private (as in private class/trait/object P {...}). Then, you can put the important public details of the API into the package object, exposing these private innards. For example, if you need to expose a protected type, you can use type aliasing for that...
After developing in scala for a while, I've noticed that a lot of people tend to use default visibility for methods and class members when they should really be private. I think this is usually done out of convenience and laziness and it's hard to enforce discipline to explicitly type private in all such cases.
Therefore, I'm interested in seeing if there's a way to require the use of an annotation, (for example, methods could be tagged as Public using scala.tools.nsc.doc.model.Public). Is there an easy way to require that all default visibility methods/members are tagged with such an annotation (possibly using maven or scalastyle)?
Is it possible to create a class (or add attributes to a class) dynamically, e.g. load field names and types from external file in Scala?
this is follow-up on Representing nested structures in scala
It is possible to achieve this with macros, and there are two techniques for that with a different set of trade-offs. Refer to our joint talk with Travis Brown for more information and a link to an example implementation: https://github.com/travisbrown/type-provider-examples/blob/master/docs/scalar-2014-slides.pdf?raw=true.
You can declare and compile a Scala class from a data structure description. It requires that you a) construct a syntactically correct class description and save it to a file (or equivalent) and then b) compile that class description to object code (i.e., a .class file). You can then load the class and use it.
This is not for the faint of heart. You need to understand the process of translation, compilation, class-loading and dynamic class binding. Even more important, you have to answer how you would actually use this in a program.
An example of dynamic class creation occurs in the Scala Play framework, where a presentation template files are translated into Scala and compiled into class files that can then be referenced from other Scala source code.
in scala i need to implement something similar to python metaclasses. in my case the goal of using the metaclasses is usually to create a registry of all the subclasses of a particular base class - that is, a mapping from say a string representation of the class to a reference to the class. in python it's very convenient to put a metaclass on the base class so that nothing special needs to be done on every subclass. i'm looking to do something similar in scala. is there any way to emulate metaclasses, or otherwise do this a different way? thanks!
If you know the fully qualified name of the class, you can load it using the usual Java reflection methods in java.lang.Class, namely Class.forName(String fqClassName). Given the resulting instance of Class, instantiation is easy only if there's a zero-argument constructor, otherwise you get entangled in the messy world of all the Java reflection types.
If you want a kind of "discovery" where classes unknown at compile time and whose names are not supplied as an input or parameter of the program in some way, then the classloader approach is probably the only answer.
There's nothing similar to python's metaclasses. The registry you speak of might be possible using custom class loaders or reflection.
Does Project Lombok offer any benefit compared to code templates / code generation in Eclipse? Are there any downsides (apart from including the .jar)?.
One advantage of Lombok is that once you've annotated a class with, say, the #Data annotation, you never need to regenerate the code when you make changes. For example, if you add a new field, #Data would automatically include that field in the equals, hashCode and toString methods. You'd need to manually make that change when using Eclipse generated methods. Some of the time, you may prefer the manual control but for most cases, I expect not.
The advantage of Lombok is that the code isn't actually there - i.e. classes are much more readable and are not cluttered.
Advantages:
Very easy to use
Classes are much cleaner ('no boilerplate code'),especially
'struct'-like inner classes shrink to a bare minimum:
#Data
private class AttrValue {
private String attribute;
private MyType value;
}
This will create both getters and setters, a toString(), and correct hash() / equals() methods including both variables.
The variant with #Value creates an immutable structure (no setters, all fields final).
No need to generate/remove code when you change fields (getters, setters, toString, hash, equals)
No interference with hand-coded methods: just add you own specific setter to the class where needed. Lombok skips this and generates everything else
Disadvantages:
No name refactoring, yet: renaming value above will not (yet) rename getValue() and setValue()
May slows down ecplise slightly
toString output not as nice as, for instance, ToStringBuilder from apache commons
Very few come to mind:
it is based on annotation, so no good for legacy project still in pre-Java5 (delombok can help). Actually, it requires using the javac v1.6 compiler.
it still have limitations regarding multiple constructors
The dependency issue is not to be overlooked though, but you have excluded it from your question.
Eclipse EMF offers some features which are very handy which Lombock does not yet support:
Powerful notification mechanims to get informed about changes in your instances
Generic API without java reflection. Access and modify instances without a strong reference to the type
Command und API based editing
Cross references between models: Create and load model trees and EMF handles the loading by creating a proxy for the cross reference. This saves memory and boost performance in huge domain trees
And much more...