Pros and Cons of Interface Constants

Pros and Cons of Interface constants

Well, I think that it boils down to the difference between good and good enough.

While in most cases you can avoid the use of constants by implementing other patterns (strategy or perhaps flyweight), there is something to be said for not needing a half dozen other classes to represent a concept. I think what it boils down to, is how likely is there a need for other constants. In other words, is there a need to extend the ENUM provided by the constants on the interface. If you can foresee needing to expand it, then go with a more formal pattern. If not, then it may suffice (it'll be good enough, and hence be less code to write and test). Here's an example of a good enough and a bad use:

Bad:

interface User {
const TYPE_ADMINISTRATOR = 1;
const TYPE_USER = 2;
const TYPE_GUEST = 3;
}

Good Enough:

interface HTTPRequest_1_1 {
const TYPE_CONNECT = 'connect';
const TYPE_DELETE = 'delete';
const TYPE_GET = 'get';
const TYPE_HEAD = 'head';
const TYPE_OPTIONS = 'options';
const TYPE_POST = 'post';
const TYPE_PUT = 'put';

public function getType();
}

Now, the reason that I chose those examples is simple. The User interface is defining an enum of user types. This is very likely to expand over time and would be better suited by another pattern. But the HTTPRequest_1_1 is a decent use-case, since the enum is defined by RFC2616 and will not change for the lifetime of the class.

In general, I don't see the problem with constants and class constants as being a global problem. I see it as a dependency problem. It's a narrow distinction, but a definite one. I see global problems as in global variables which are not enforced, and as such create a soft global dependency. But a hard-coded class creates an enforced dependency, and as such create a hard global dependency. So both are dependencies. But I consider the global to be far worse since it's not enforced... Which is why I don't like to lump class dependencies with global dependencies under the same banner...

If you write MyClass::FOO, you're hard-coded to the implementation details of MyClass. This creates a hard-coupling, which makes your code less flexible, and as such should be avoided. However, interfaces exist to permit exactly this type of coupling. Therefore MyInterface::FOO doesn't introduce any concrete coupling. With that said, I wouldn't introduce an interface just to add a constant to it.

So if you're using interfaces, and you're very sure that you (or anyone else for that matter) won't need additional values, then I don't really see a huge issue with the interface constants... The best designs wouldn't include any constants or conditionals or magic-numbers or magic-strings or hard-coded anything. However, that adds additional time to the development, as you must consider the uses. My view is that most times it's absolutely worth taking the additional time to build a great solid design. But there are times when good enough really is acceptable (and it takes an experienced developer to understand the difference), and in those cases it's fine.

Again, that's just my view on it...

For what purpose can you declare constants in a Java interface?

A constant is part of an interface, too. Constant values are used in design to avoid Magic Numbers, i.e. numbers which have a certain meaning to the implementation, but seem to pop out of nowhere.

There are many cases where numerical values influence the behavior of the code. Consider, for example, an interface for a GUI button. How this button is actually drawn is up to the implementation; but what kind of button it is is part of the contract which forms the interface: Is it a normal push button, has it an image, or is it a checkbox? This behavior can be modified using constants, commonly used by OR'ing values: For example, int buttonType = PUSHBUTTON|IMAGEBUTTON.

How to associate constants with an interface in C#?

C# 8 now allows constants in an interface definition.

TypeScript: Interface or type for one of constants or string

The error is because you have only defined ERROR_A as a value but you are trying to use it as a type. (The error message is unhelpful; I recently filed an issue to improve it.) To define each name as both a value and a type, you could use the following in constants.ts:

export const ERROR_A = "Error A";
export type ERROR_A = typeof ERROR_A;
export const ERROR_B = "Error B";
export type ERROR_B = typeof ERROR_B;
export const ERROR_C = "Error C";
export type ERROR_C = typeof ERROR_C;

Hayden Hall's suggestion to use an enum is also good, since enum members are automatically defined as both names and types. But you could avoid all of this and just write type SWITCH_ERROR = string; it's equivalent to type SWITCH_ERROR = ERROR_A | ERROR_B | ERROR_C | string when ERROR_A, ERROR_B, and ERROR_C are specific strings.

What are the pros and cons of using interfaces in Delphi?

All I can think of for now:

Pros:

  • Clear separation between interface and implementation
  • Reduced unit dependencies
  • Multiple inheritance
  • Reference counting (if desired, can be disabled)

Cons:

  • Class and interface references cannot be mixed (at least with reference counting)
  • Getter and setter functions required for all properties
  • Reference counting does not work with circular references
  • Debugging difficulties (thanks to gabr and Warren for pointing that out)

Why to use Interfaces, Multiple Inheritance vs Interfaces, Benefits of Interfaces?

Interfaces are collection of final static fields and abstract methods (Newly Java 8 added support of having static methods in an interface).

Interfaces are made in situations when we know that some task must be done, but how it should be done can vary. In other words we can say we implement interfaces so that our class starts behaving in a particular way.

Let me explain with an example, we all know what animals are. Like Lion is an animal, monkey is an animal, elephant is an animal, cow is an animal and so on. Now we know all animals do eat something and sleep. But the way each animal can eat something or sleep may differ. Like Lion eats by hunting other animals where as cow eats grass. But both eat. So we can have some pseudo code like this,

interface Animal {
public void eat();
public void sleep();
}

class Lion implements Animal {
public void eat() {
// Lion's way to eat
}

public void sleep(){
// Lion's way to sleep
}
}

class Monkey implements Animal {
public void eat() {
// Monkey's way to eat
}

public void sleep() {
// Monkey's way to sleep
}
}

As per the pseudo code mentioned above, anything that is capable of eating or sleeping will be called an animal or we can say it is must for all animals to eat and sleep but the way to eat and sleep depends on the animal.

In case of interfaces we inherit only the behaviour, not the actual code as in case of classes' inheritance.

Q1. As interfaces are having only abstract methods (no code) so how can we say that if we are implementing any interface then it is inheritance ? We are not using its code.

Implementing interfaces is other kind of inheritance. It is not similar to the inheritance of classes as in that inheritance child class gets the real code to reuse from the base class.

Q2. If implementing an interface is not inheritance then How interfaces are used to achieve multiple inheritance ?

It is said because one class can implement more than one interfaces. But we need to understand that this inheritance is different than classes' inheritance.

Q3. Anyhow what is the benefit of using Interfaces ? They are not having any code. We need to write code again and again in all classes we implement it.

Implementing an interface puts compulsion on the class that it must override its all abstract methods.

Read more in my book here and here

In Java, how to iterate on the constants of an interface?

Using reflection:

Field[] interfaceFields=HttpConstants.class.getFields();
for(Field f:interfaceFields) {
//do something
}

But anyway, if you can redesign your class, I would recomend you to handle a static enum constants construction. So, suposing your class will contain always an int value for every constant:

enum HttpConstants {

HTTP_OK(200), HTTP_CREATED(201), HTTP_ACCEPTED(202),
HTTP_NOT_AUTHORITATIVE(203),HTTP_NO_CONTENT(204),
HTTP_RESET(205), HTTP_PARTIAL(206) /* ... */;

private int value;

HttpConstants(int aValue) {
value=aValue;
}

public int getValue() {
return value;
}
}

Then, to loop on it:

    for(HttpConstants val: HttpConstants.values()) {
int value=val.getValue();
//...
}

Thus, avoiding the access to the reflection API.

Morbid use of constants

You should not. The INTEGER_ONE name is no more meaningful than 1. If however this value has some other meaning (for example, month in the year), then using a constant (like Calendar.FEBRUARY) will make your code clearer.

I can guess that this constant in Commons Math library was created in Java 1.4 when there were no Integer cache and autoboxing, so it had sense in terms that you may reuse the same Integer object (not primitive int) in different places to save memory. So it was added for performance reasons, not for code clarity. Now it's obsolete: even if you need an Integer object, you can use Integer.valueOf(1) or implicit autoboxing and get the cached one.



Related Topics



Leave a reply



Submit