8

...As this forces us to create getters and setters, which in practice are often totally extraneous? Is there any good language-design reason why interfaces in most (all?) languages do not allow member fields to help fulfill the interface spec?

In most extant languages, members are treated fundamentally differently from methods, but does this HAVE to be the case? In a theoretical language, couldn't we have an interface that (a) specified a zero-args method as getter, but accepted a readable member as its implementor, and (b) specified a single-arg method as a setter, but accepted a writable member field as its implementor, given a language that supported specifying direct access control on variables when they are declared? A prototypal language allowing multiple inheritance (to address the very valid point some respondents have made), would be ideal for something like this.

Please inform me if something like this already exists.

Engineer
  • 781

11 Answers11

10

In most extant languages, member [fields?] are treated fundamentally differently from methods, but does this HAVE to be the case?

Yes, it does.

Member fields are per-instance data. Data must actually exist somewhere in memory for every instance - there must be an address or sequence of addresses reserved for it. In Java, .NET, and many other OO languages, this data goes on the heap.

Methods are per-class data. They are pointers to a vtable. That's how methods get virtual dispatch. There is only actually one instance allocated, per class.

An interface is essentially a special type of class that only contains methods, no instance data. That's part of the definition of interface. If it contained any data, it wouldn't be an interface anymore, it would be an abstract class. Both of those choices are fine, of course, depending on what kind of design pattern you're trying to implement. But if you added instance data to interfaces, you'd take away everything that makes them interfaces.

OK, so why can't an interface method point to a member field? Because there's nothing at the class level to point to. Again, an interface is nothing but a method table. The compiler can only generate one table, and every method in it has to point to the same memory address. Thus it's impossible for interface methods to point to class fields, because the class field is a different address for every instance.

Perhaps the compiler could accept this anyway and generate a getter method for the interface to point to - but then that essentially becomes a property. If you want to know why Java doesn't have properties, well... that's a really long and tedious story that I'd rather not get into here. But if you're interested, you might want to have a look at other OO languages which do implement properties, such as C# or Delphi. The syntax is really easy:

public interface IFoo
{
    int Bar { get; }
}

public class Foo : IFoo
{
    public int Bar { get; set; }
}

Yep, that's all there is to it. Important: These are not fields, the "int Bar" in the Foo class is an Auto Property, and the compiler is doing exactly what I just described above: automatically generating getters and setters (as well as the backing member field).

So to recap the answer to your question:

  • Interfaces require methods because their entire purpose is not to contain any data;
  • The reason that there is no syntactic sugar to make it easier for a class to implement an interface is simply that the Java designers do not will it - and by this point in time, backward compatibility is an issue. Language designers make these kinds of choices; you'll just have to deal with it, or switch.
Aaronaught
  • 44,523
9

this is a result of information hiding, i.e. those members shouldn't be visible as fields but as properties that may or may not be stored/cached locally

one example is a the hash code it changes when the object changes so it is better to calculate it when it is asked for and not each time the object changes

besides most languages are single-inheritance + multi-implements and allowing fields to be part of interfaces puts you into multi-inheritance territory (only thing missing is default implementation of functions) which is a minefield of edge cases to get right

ratchet freak
  • 25,986
6

Member variables are the implementation of the class, not the interface. You may want to change the implementation, so other classes shouldn't be permitted to refer to that implementation directly.

Consider a class with the following methods - C++ syntax, but that isn't important...

class example
{
  public:
    virtual void Set_Mode (int p_mode);
    virtual int  Mode () const;
};

It seems pretty obvious that there's going to be a member variable called mode or m_mode or similar that directly stores that mode value, doing pretty much what a "property" would do in some languages - but that's not necessarily true. There's a lot of different ways this could be handled. For example, the Set_Mode method might...

  1. Identify the mode using a switch statement.
  2. Instantiate a subclass of some internals class, depending on that mode value.
  3. Store a pointer to that instance as a member variable.

Having done that, many other methods of the example class might then call appropriate methods of that internals class through the pointer, getting mode-specific behaviour without needing to check what the current mode is.

The point here is less that there's more than one possible way to implement this kind of thing, and much more that at some time you may change your mind. Maybe you started with a simple variable, but all the switch statements to identify the mode in every method are getting a pain. Or maybe you started out with the instance-pointer thing, but that turned out to be too heavyweight for your situation.

It turns out that things like this can happen for any member data. You may need to change the units that a value is stored in from miles to kilometers, or you may find that your uniquely-identify-the-case enumerate can no longer uniquely identify all the cases without considering some extra information, or whatever.

This can happen for methods too - some methods are purely for internal use, depend on the implementation, and should be private. But many methods are part of the interface, and won't need to be renamed or whatever just because the internal implementation of the class has been replaced.

Anyway, if your implementation is exposed, other code will inevitably start to depend on it, and you'll be locked into keeping that implementation. If your implementation is hidden from other code, that situation cannot happen.

Blocking access to implementation details is called "data hiding".

3

As others have noted, an interface describes what a class does, not how it does it. It's essentially a contract that inheriting classes must conform to.

What you describe is slightly different - a class that provides some implementation but perhaps not all, as a form of reuse. These are generally known as abstract classes and are supported in a number of languages (e.g. C++ and Java). These classes cannot be instantiated in their own right, they can only be inherited by concrete (or further abstract) classes.

Again as noted already, abstract classes tend to be of most value in languages that support multiple-inheritance as they can be used to provide pieces of additional functionality to a larger class. This is often considered bad style, however, as generally an aggregation ("has-a") relationship would be more appropriate

Steve Mallam
  • 306
  • 1
  • 2
3

Obviously in most extant languages, members are treated fundamentally differently from methods, but does this HAVE to be the case?

Not for any theoretically-grounded reason. I think the reasons you don't see it often are practical:

The first is how you deal with these things at runtime. In Java or C++, an assignment to a primitive-typed public member like foo.x = 5 is easy to deal with: stuff 5 into some register, figure out where in memory the x member of foo lives and dump the register there. In a language like C# where classes can encapsulate intercepting assignments to members or pre-calculate how those members will evaluate, the compiler will have no a priori knowledge of whether the implementation of a class made available at runtime uses that feature. That means all public member assignments and evaluations of public members have to be deferred to the implementation.* Operations involving a lot of access to those members end up taking a performance hit because they're constantly doing subroutine calls that could be handled faster with regular in-line assignments. Leaving evaluation and assignment separate from getters and setters gives the developer some control over how they're handled in a given situation.

The second is age. With the possible exception of F#, none of the languages in very wide use today is any younger than a decade, and even as recently as back then, the additional cycles required to make intercepted evaluation and assignment possible may not have been acceptable.

Third is inertia. I think to some degree, there's still some stigma associated with doing direct assignment to public members even if the language does allow the class to manipulate them and people still think in terms of getters and setters being better. That will wear off with time, just as it did with all of the people who had their noses in the air over people who wrote programs in higher-level languages instead of assembly.


*There's a tradeoff that comes with this: a language has to go whole hog with deferring evals/assignments to the class or balk at runtime if code using in-line evals/assignments for a given class tries to link with an implementation that intercepts them. Personally, I think the latter is a bad idea because it forces recompilation of code that uses an API that's unchanged.

Blrfl
  • 20,525
1

Please inform me if something like this already exists.

Objective-C properties provide this sort of functionality with its synthesized property accessors. An Objective-C property is essentially just a promise that a class provides accessors, typically of the form foo for the getter and setFoo: for the setter. The property declaration specifies certain attributes of the accessors related to memory management and threading behaviors. There's also a @synthesize directive which tells the compiler to generate accessors and even the corresponding instance variable, so you don't have to bother writing getters and setters or declaring an ivar for each property. There's also some syntactic sugar that makes property access look like accessing the fields of a struct, but actually results in calling the property accessors.

The result of all that is that I can declare a class with properties:

@interface MyClass : NSObject
{}
@property (assign) int foo;
@property (copy) NSString *bar;
@end

and then I can write code that looks like it accesses ivars directly, but in fact uses accessor methods:

MyClass *myObject = [[MyClass alloc] init];  // create myObject

// setters
myObject.foo = 127;                 // same as [myObject setFoo:127];
myObject.bar = @"Hello, world!";    // same as [myObject setBar:@"Hello, world!"];

// getters
int i = myObject.foo                // same as [myObject foo];
NSString *s = myObject.bar          // same as [myObject bar];

It's been said already that accessors let you separate interface from implementation, and the reason that you want to do that is to preserve your ability to change the implementation in the future without affecting client code. The drawback is that you have to be disciplined enough to write and use accessors just to keep your future options open. Objective-C makes generating and using accessors as easy as using ivars directly. In fact, because they take care of much of the work of memory management, using properties is actually a lot easier than accessing ivars directly. And when the time comes that you want to change you implementation, you can always provide your own accessors instead of letting the compiler generate them for you.

Caleb
  • 39,298
1

Why do interfaces require methods over members?

...As this forces us to create getters and setters, which in practice are often totally extraneous? Is there any good language-design reason why interfaces in most (all?) languages do not allow members to help fulfill the interface spec?

"Most" languages? Which languages have you investigated? In dynamic languages there are no interfaces. There are only three or four statically typed OO languages with any popularity: Java, C#, Objective-C, and C++. C++ doesn't have interfaces; instead we use abstract classes, and an abstract class can contain a public data member. C# and Objective-C both support properties, so there is no need for getters and setters in those languages. That leaves only Java. Presumably the only reason Java does not support properties is that it has been difficult to introduce them in a backward-compatible fashion.

kevin cline
  • 33,798
1

Some of the answers mention 'information hiding' and 'implementation details' as the reason interface methods are preferred over fields. I think the main reason is simpler than that.

Interfaces are a language feature that allow you to swap out behavior by having multiple classes implement an interface. The behavior of a class is defined by its methods. Fields, on the other hand, only reflect the state of an object.

Of course, the fields or properties of a class may be part of the behavior, but they aren't the important part of the contract defined by the interface; they are only a result. Which is why e.g. C# allows you to define properties in an interface, and in Java you define a getter in the interface. This is where a bit of information hiding comes into play, but it's not the main point.

As I said before, interfaces allow you to swap out behavior, but let's have a look at the swapping out part. An interface allows you to change the underlying implementation by creating a new implementing class. So having an interface consisting of fields doesn't make much sense, because you can't change much about the implementation of fields.

The only reason you'd want to create a field-only interface is when you want to say that some class is a certain type of object. I've emphasized the 'is a' part, because you should be using inheritance rather than interfaces.


Side-note: I know that composition it preferred over inheritance and composition can usually only be achieved by using interfaces, but using interfaces just to 'tag' a class with some properties is just as bad. Inheritance is great when used appropriately, and as long as you stick to the Single Responsibility Principle, you shouldn't have any problems.

I mean, I've never worked with a UI control library for example, which doesn't use inheritance. The only area where interfaces come into play here is in data provisioning, e.g. an ITableDataAdapter to bind data to a table control. This is exactly the type of thing interfaces are meant for, to have interchangeable behavior.

0

In Java the reason is that interfaces only allow specifying methods.

Therefore if you want anything with a field in the interface contract, you need to do it as a getter and a setter method.

Also see this question: When are Getters and Setters Justified

-1

The point of an interface is to specify functions you must implement in order to claim to support this interface.

-1

Members aren't allowed in interfaces because then those languages would have to deal with the horrendous evil that is, multiple inheritance.

DeadMG
  • 36,914