I have seen constructs with an enum declared inside an enum. What is this used for ?
Enums in Java can't be extended, so if you wanna collate strongly-related enums in one place you can use these nested enum constructs. For example:
public enum DepartmentsAndFaculties
{
UN (null, "UN", "University"),
EF (UN, "EF", "Engineering Faculty"),
CS (EF, "CS", "Computer Science & Engineering"),
EE (EF, "EE", "Electrical Engineering");
private final DepartmentsAndFaculties parent;
private final String code, title;
DepartmentsAndFaculties(DepartmentsAndFaculties parent, String code, String title)
{
this.parent = parent;
this.code = code;
this.title = title;
}
public DepartmentsAndFaculties getParent()
{
return parent;
}
public String getCode()
{
return code;
}
public String getTitle()
{
return title;
}
}
Here, inner enums consist of {parent enum, code, title} combinations. Example usage:
DepartmentsAndFaculties cs = DepartmentsAndFaculties.CS;
cs.getTitle();
You can see the power of nested enums when constructing hierarchical entities/enums.
You might mean an Enum as an inner type. This is most typically seen when the outer type is a class or an interface, but I suppose there isn't any reason this couldn't be done with enum as an outer.
Inner types are partly about code organization. They can be useful in avoiding creating a bunch of separate files when you have a few types that are related. Sometimes it can make type name more intuitive. For instance, see Map class and its inner Entry class. Most external references to Entry would use Map.Entry format, which is very readable.
The other reason for inner types is that if outer type is a class or an enum, then inner type can be non-public. This is useful for hiding types that are implementation details of the outer type.
I have used nested enums in rare cases where I wanted to enforce a naming convention on the enum values, if additions of new names would have implications for operations or other folks. Here's one example:
public enum MessageTemplateName {
account_verify,
vendor_job_request,
account_job_confirmed,
vendor_job_confirmed,
account_friend_request,
account_job_accepted,
vendor_job_accepted_by_other;
/** Make sure you tell operations if you're adding a new recipient */
private enum Recipient { account, vendor }
private Recipient recipient;
private String messageName;
MessageTemplateName () {
final int firstUnderscore = name().indexOf('_');
recipient = Recipient.valueOf(name().substring(0, firstUnderscore));
messageName = name().substring(firstUnderscore+1);
}
public String getTemplateUrl (String baseUrl) {
if (!baseUrl.endsWith("/")) baseUrl += "/";
return baseUrl + recipient.name() + "/" + messageName + ".vm";
}
}
I'm using an Enum because I want to be able to pass around a generic "message template name" in various places. As you can see, the first part of the enum name corresponds to a directory on a server, and the remainder of the name refers to a Velocity template file name. If fellow engineers started introducing new constants, I'd want to make sure they were filed under the appropriate "recipient", or if a new recipient legitimately needs to be created, that it's a conscious effort to do so, and you'll inform operations (create the directory in production, put any monitoring/permissions in place, etc).
There's a decent argument that, if at some point your Enum becomes too complex, you can replace it with a class/class hierarchy coupled with a much simpler enum. Not sure where I draw the line, but I suppose the above is heading in that direction.
Related
so I have been trying to understand what property exactly mean. I have searched for previously asked Q/A in stackoverflow and other website but the answers that I came across were not specific as to whether fields(instance variables) that are modified with setters and getters are also called properties.
The definition I came across was "a combination of setters and getters methods that modify fields of an object"
Below is just a small piece of code to make you understand my question better if you need more clarification.
//property?
String name;
//property?
public void setName(String n){
name = n;
}
//property?
public String getName(){
return name;
}
Properties means any members that belongs to the class. It could be variable, objects of other/ same class, methods of that class etc.
basically getter/setter are used for those member variables only.
Local variables are properties of that method that it belongs to and not property of the class.
In the OOP world, "property" has a rather broad sense and its specific meaning depends on the context. Generally, it is an attribute of an entity; ith may be a name or an age of a person, a color of a flower, a height of a building etc. A property has its name and its value (e.g. flower.color = red -- here color is the name, and red is the value), the value may belong to different types (or classes): a string, a number, a person, an enterprise... It may have a constant value (that never change during the lifetime of the owner (the entity it belongs to)) or it may have a variable value that can be changed by the user. In the software area it can be talked about at a conceptual level of the domain analysis and the software design; in this case people usually don't care how exactly it would be implemented. As well, it may be used at the level of concrete implementation (program code), and then the means to implement this concept depend on the programming language.
In Java, for example, when we say 'property' we usually mean a field (variable) of an object and a couple of methods (or a single method for read-only properties) to access its value (getter and setter):
class Person {
private String name; // the field to hold the value
public Person(String name) { // Constructor
this.name = name // The name is given at the moment it's been born
}
public String getName() { return Name; } // getter
// No, name can't be changed after it's been born -- it's a read-only property, thus no setter
// public void setName(String name) { this.name = name; } // otherwise the setter would look like this
}
In such a case, a user can acces the value of the property with the following code:
System.out.println(thisPerson.getName());
Other languages (like C#, for example) have means to code properties in somewhat more convenient way:
class AnotherPersonType {
private string name // a field to hold the value
public string Name
{
get => name; // getter, the same as "return this.name;"
set => name = value; // setter, the same as "this.name = value;"
}
}
.....
anotherPerson.name = "John"; // It looks like an assignment,
// but in fact, the setter is invoked
I was reading this article on why getter and setters are evil. The article doesn't say not to use them ever, but, it's telling you to think in a way that limits the use of those methods, or to quote the article:
Don't ask for the information you need to do the work; ask the object
that has the information to do the work for you.
what happens when you need to display data in a GUI, but don't have getter methods? The article covers this briefly, but not fully. It mentions passing a JComponent to the class, but if you're GUI changes, it could lead to a lot of work to fix.
Take for example, you have a Book class (making this example limited to keep it readable).
public final class Book {
private String title;
//Authors is class with the attributes authorFirstname, authorLastname
private List<Author> listofAuthors;
public Book(String title, List<Author> listofAuthors)
{
//initialization
}
//other methods that do work
}
If I have a GUI that has a JTextField to display the book title and a JTable to display the list of authors, how would I write my method to "do the work" for me and display the result? Is this one of those times where a getter is necessary?
Allen Holub's article (the one you mentioned) is completely right, you shouldn't ask for data, at least when you're doing Object-Orientation. And no, displaying things is not a valid excuse to open up an object.
If you have a Book, just ask for the Book to display itself! It shouldn't matter whether that uses a JTextField or JTable or whatever. Depending on your requirements of course, you could do:
public final class Book {
...
JComponent display() {
...
}
}
The point of Object-Orientation is of course, that you are trying to localize changes (restrict to one class as much as possible). The only way to do that is to localize the functionality that depends on the same things into (preferably) the same class. Also called increasing "cohesion".
So now, if the Book internals change, all of the things, including how the Book is displayed is in the Book itself, so there is no need to "hunt" for code that uses the Book.
Now, for the answer that this is not "clean", because you are mixing presentation code with "business logic". It may be interesting to note, that the whole idea of not mixing presentation with "business logic" comes from earlier times, when we still thought that presentation might be "remote" to the "business objects", where "business objects" might be used by multiple applications for different things. Ie. multi-tier designs. YAGNI. Most of the time there is no real reason to have artificial technical boundaries inside a single application. There is no harm done if the Book knows it's part of a GUI application, and there are real benefits (maintainability) to have.
Edit: this is how the `display() method could look like in detail, with displaying the title and authors (pseudocode for Swing):
public final class Book {
private final String title;
private final List<Author> authors;
...
public JComponent display() {
JPanel bookPanel = new JPanel();
bookPanel.add(new JLabel(title));
JList authorsList = new JList(); // Or similar
for (Author author: authors) {
authorsList.add(author.display());
}
bookPanel.add(authorsList);
return bookPanel;
}
}
And then you can simply add() that component to whatever swing container you want to display the book in.
Think of it this way: Getters (public functions) are a bridge for private attributes.
I'll write you a simple example to modify your TextField using OOP.
Book class:
public final class Book {
private String title;
//Authors is class with the attributes authorFirstname, authorLastname
private List<Author> listofAuthors;
public Book(String title, List<Author> listofAuthors)
{
//initialization
}
public String getTitle() {
return this.title; }
}
GUI:
author1 = new Author("jhon");
author 2 = new Author("alsojhon");
list = new ArrayList();
list.add(author1);
list.add(author2)
b = new Book("stack",list);
JTextField field;
field.setText(b.getTitle());
You can create three kind of classes:
Entity, classes that represents a business concept and have only one unique id, like Client class with Id the username. It is usually a mutable class. You should have all the business logic here. You should not open his data with getters and setters.
Value object, classes that represents a business concept but not have an unique id, like Email class. It is usually an imm.utable class. You should have all the business logic here.
Data structure (kind of DTO), classes to save data only, without behavior, maybe you have setters and getters to access those datas.
What can I do if I need to access all Client data if I do not have accesors? Well, you should transform Client to a DTO. You can use a framework like Orika. Or you can create a method into Client class to ask for information (mediator pattern).
I like second option but it implies more work:
class Client{
private String name;
...
public void publishInfo(ClientInfo c){
c.setName(name);
...
}
}
class ClientInfo{
private String name;
//GETTERS
//SETTERS
}
Are you asking about a method to display all the information for you? I'm not following.
If that is what you're asking, here's my recommendation: Don't write it in the class with the window code in it. It won't be very clean. Make a new class with that method in it (Yes, getters are necessary, they make OOP easier, but that's biased).
What I do if I want to iterate through a list is make a StringBuilder, along with a for loop, that adds the name of the author. Then, have the method return the list of authors.
List<Authors> a;
StringBuilder d = new StringBuilder();
for (int i = 0; i < a.size(); i++) {
d.append(a.get(i).getName() + ", ");
}
return d.toString();
//It's just sudo code, but still.
My question is "is it possible to have an int identifier in an enum?"
I'm developping a java program and I need to have identifiers that contains numbers and letters but eclips doesn't accept it.
for exapmle
public enum Tag{
5F25,
4F,
.
.
.
}
Do anyone know if there is any way to solve this problem!
Thank you
Enum instances must obey the same java language naming restrictions as other identifiers - they can't start with a number.
If you absolutely must have hex in the name, prefix them all with a letter/word, for example the enum class itself:
public enum Tag {
Tag5F25,
Tag4F,
...
}
or maybe with an underscore and all-caps:
public enum Tag {
TAG_5F25,
TAG_4F,
...
}
etc
You're trying to bend the laws and conventions of programming. I suggest you take a different approach.
Enums can have constructors. They are usually private, because "instances" of the enum are created inside it. You can provide any info you want (e.g. id, name, keyword etc.).
In this example, I've implemented the enum with just one parameter in the constructor, which is the unique ID you're needing.
public enum Tag
{
TAG_1(1),
TAG_2(2),
TAG_3(3);
private final int id;
private Tag(final int id)
{
this.id = id;
}
public int id() // Objective C style. Can be getId()
{
return id;
}
/**
* Bonus method: get a Tag for a specific ID.
*
* e.g. Tag tagWithId2 = Tag.getTagForId(2);
*/
public static Tag getTagForId(final int id)
{
for (final Tag tag : values())
if (tag.id == id)
return tag;
return null;
}
}
In a word, No. Java enum's are basically syntactic sugar for the typesafe enum pattern. This means that the enum is a list of java identifiers: Their names have to follow all the rules for identifiers. One of those rules is that identifier names cannot start with a number.
I have to choose from several types of genres for books and I was thinking using enums for this, but there are several genres composed by two or more words like "Medical, Health & Fitness", "Art & Photography", "Science Fiction", etc.
public enum Genero {
Action, Comedy, Drama, Computers, Novel, Science Fiction
}
But I got a syntax error for "Science Fiction". I tried putting it with double quotes and simple quoutes, but neither worked. This enum is going to be use as a attribute for Book class.
No, it's not possible. Enum names must be valid Java identifiers - that means, no spaces. The usual convention is to declare enum names in all upper-case characters and separate words using an underscore, like this:
public enum Genero {
ACTION, COMEDY, DRAMA, COMPUTERS, NOVEL, SCIENCE_FICTION
}
It is not possible. It is possible, however, to use an underscore (Science_Fiction) in the name. You can also override the toString method to return whatever you want it to (since it appears you are going for a human-readable name for your enums):
public enum Genero {
ACTION("Action"), COMEDY("Comedy"), DRAMA("Drama"), COMPUTERS("Computers"), NOVEL("Novel"), SCIENCE_FICTION("Science Fiction");
private final String toString;
private Genero(String toString) {
this.toString = toString;
}
public String toString(){
return toString;
}
}
This might be what you want:
static private enum EnumExample {
R("Sample emun with spaces"),
G("Science Fiction");
final private String value;
EnumExample(String s) {
value = s;
}
}
System.out.println(EnumExample.G.value);
System.out.println(EnumExample.valueOf("G").value);
Science Fiction
Science Fiction
I write a little web API which should it make easy to create URIs. Each resource class should contain a method createURI which takes the needed parameters. This method should use a helper method, populateUriTemplate, in the background to create an URI string. populateUriTemplate needs key value pairs to populate an URI template. In another language like Scala or Python I would use named parameters, but Java doesn't support them. So the question is: How to simulate named parameters in Java?
The straight forward solution would be to create a map:
public String createUri(int id, String name){
Map<String, Object> params = new HashMap<String, Object>();
params.put("id", id);
params.put("name", name);
return populateUriTemplate(params);
}
But I don't like to create a map first and put each parameter to it.
Another idea is to use a static method, param, to create key value pairs:
public String createUri(int id, String name){
return populateUriTemplate(param("id", id), param("name", name));
}
Looks much better to me!
It could be refined a bit to make it more self-explanatory, even if a few more characters are needed:
public String createUri(int id, String name){
return populateUriTemplate(key("id").value(id), key("name").value(name));
}
I've also thought of the builder pattern, but this would force the user of my API to create an explicit builder for each resource class, what would be tedious without a benefit. The type of the parameter is not important, as long as a proper implemented toString method exists.
My favourite is one of the both approaches with the static methods above (param(key, value) or key(k).value(v)). Do you know a better way to simulate named parameters in this case?
For some ideas on the builder pattern, you could see this blog post by Stephan Schmidt.
You also just gave me the idea to do the following, with fluent interfaces, a Callable, and a static method:
createUri().id(5).name("dennetik").call();
Which would require createing a Callable class (CreateUri) with the static method:
public static final CreateUriFluentInterface createUri() {
return FluentInterface.of(new CreateUri(), CreateUriFluentInterface.class);
}
And a fluent interface, like this:
public interface CreateUriFluentInterface {
public CreateUriFluentInterface id(Integer id);
public CreateUriFluentInterface name(String name);
}
Which isn't that much boilerplate code, is it?
(Well, if you tone down that horribly named CreateUriFluentInterface a bit, it isn't.)
(You would probably have CreateUriFluentInterface extend Callable<String>, to be able to reroute the call to Callable#call())
populateUriTemplate("id",id, "name",name);
void populateUriTemplate(Object... nvs){
for(int i=0; i<nvs.length/2; i++)
....
}
Maybe you like this approach:
class Params {
private HashMap<String, Object> allParams = new HashMap<String,Object>();
public Params(ParamEntry...params) {
for( ParamEntry p : params ) {
allParams.put(p.name, p.value);
}
}
public getParam(String name) {
return allParams.get(name);
}
class ParamEntry {
public String name;
public Object value;
}
}
public String createUri(Params.ParamsEntry ... params){
return populateUriTemplate(new Params(params));
}
To call it use
createUri(new Param.ParamEntry("name", valueObject) );
Inside the populateUriTemplate...
just use params.get("name");
Spring MVC does exactly this. As well as being able to bind requests to specific methods in controller classes, you can bind request parameters to method parameters. You can have a look to see how it works, but basically it picks a strategy to map the right request parameter to the right method parameter.
You basically get something like:
public String createUri(#RequestParam int id, #RequestParam String name){
return populateUriTemplate(id, name);
}
This is almost silly and slightly off topic, but using Lombok's #Builder annotation takes this closer to the desired result.
Furthermore if the builder, builder method and build method names are changed to _ they almost disappear:
import static foo.Template._;
class Resource {
String createURI(String id, String name) {
return populateURITemplate(_.id(id).name(name)._());
}
String populateURITemplate(Template t ){
return t.id+"="+t.name;
}
}
#Builder(builderClassName = "_", builderMethodName = "_", buildMethodName = "_" )
class Template {
static _ _ = _();
String id;
String name;
}
Named parameters are not the way:
Named parameters do not make your code any cleaner in this case. I would argue that they make things more complex and error prone in Java because you lose type safety and you lose compiler warnings about identifiers that do not exist.
TypeSafe Immutable Fluent Builders:
I wrote an article on a UrlBuilder implementation earlier this year, it shows a type safe fluent interface that enforces order of construction for mandatory input and allows for optional parts with sane defaults as well.
Now I will be the first to admit that the approach I use is fairly verbose, but it is extremely productive once that initial price is paid. It works with dependency injection and is easily unit testable and most importantly is composable for specialization.
final URL url1 = new UrlBuilder().scheme("http").host("www.google.com").build();
System.out.println("url1 = " + url1);
final URL url2 = new UrlBuilder().scheme("https").userInfo("xkcd", "correcthorsebatterystaple").host("admin.xkcd.com").build();
System.out.println("url2 = " + url2);
Produces:
url1 = http://www.google.com
url2 = https://xkcd:correcthorsebatterystaple#admin.xkcd.com
I am addressing the verbosity of the anonymous inner class implementations of the interfaces with another approach I am experimenting with; type safe implementations of value objects from interfaces using dynamic proxies.
This will do away with the boilerplate value objects and replace them with Map<String,?> but put a dynamically generated type safe immutable Interface wrapper around them.
I encourage you to read about both of these and see how combining them gives you a better solution than named properties ever would.
When I get time to refactor my UrlBuilder with the dynamic proxies I will post another blog post about it as well.
Named Parameters via Guice
If you are dead set on named parameters then I would recommend looking at Guice #Named bindings. You still lose the compile type checks and safety but at least you get some validations from Guice.
public class RealBillingService implements BillingService {
#Inject
public RealBillingService(#Named("Checkout") CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}