Why only public methods on interfaces?

K

kramer31

Could someone please explain to me the rational behind only allowing
public methods on interfaces? In my mind, protection and interfaces
are two independent if perhaps somewhat related concepts.

For instance, I have an aspect which creates a proxy of a given
interface (which handles transaction propagation). Now in order to
use this aspect, I need an interface (otherwise, no proxy can be
created). However, I have some methods on this class which I would
like to proxy which are public, some are protected, some are package.
Because of this stupid restriction, I have to make all of the methods
public, or do ridiculous things with protection on inner classes.

There are other examples, too. In fact one could imagine a case where
one would only want protected methods on an interface.

Yuck, Java, yuck.
 
A

Arved Sandstrom

Could someone please explain to me the rational behind only allowing
public methods on interfaces? In my mind, protection and interfaces
are two independent if perhaps somewhat related concepts.

For instance, I have an aspect which creates a proxy of a given
interface (which handles transaction propagation). Now in order to
use this aspect, I need an interface (otherwise, no proxy can be
created). However, I have some methods on this class which I would
like to proxy which are public, some are protected, some are package.
Because of this stupid restriction, I have to make all of the methods
public, or do ridiculous things with protection on inner classes.

There are other examples, too. In fact one could imagine a case where
one would only want protected methods on an interface.

Yuck, Java, yuck.

I can't agree with your take on things here, with all due respect. To me
that is what an interface is for - it's the set of public methods that
you want an implementing object, including a proxy, to present to the
rest of the world.

And proxies in Java, by definition, implement a list of interfaces.
That's what they are for.

Maybe it's just me, but if I wanted an object that implemented public,
protected and private methods, I'd construct an instance of a class that
defines all those methods. Is there any reason you can't have a class
that implements the transaction interface in question?

AHS

--
That's not the recollection that I recall...All this information is
certainly in the hands of the auditor and we certainly await his report
to indicate what he deems has occurred.
-- Halifax, Nova Scotia mayor Peter Kelly, who is currently deeply in
the shit
 
J

Joshua Cranmer

Could someone please explain to me the rational behind only allowing
public methods on interfaces? In my mind, protection and interfaces
are two independent if perhaps somewhat related concepts.

An interface is a public contract of methods that an object guarantees
it will support. In my view, the idea of an interface is that you are
letting someone else do the implementing. That "someone else" part
implies that the methods can't be package-protected, since it might not
be in your package. Private interface methods would of course be
useless, and protected methods would be severely limited to only the
implementing classes. In my mind, protected means "it's really private,
but you need to have your children see or use them", which suggests that
a protected method is inherently tied up in the implementation as
opposed to an interface.
For instance, I have an aspect which creates a proxy of a given
interface (which handles transaction propagation). Now in order to
use this aspect, I need an interface (otherwise, no proxy can be
created). However, I have some methods on this class which I would
like to proxy which are public, some are protected, some are package.
Because of this stupid restriction, I have to make all of the methods
public, or do ridiculous things with protection on inner classes.

You can use abstract classes where reasonable; where not reasonable, it
is also possible to make top-level package-private interfaces.
There are other examples, too. In fact one could imagine a case where
one would only want protected methods on an interface.

I would use an abstract class in that case. Think about stuff like an
AbstractDefaultImpl class, which implements most of the methods on top
of a simpler protected interface.
 
S

Stefan Ram

kramer31 said:
For instance, I have an aspect which creates a proxy of a given
interface (which handles transaction propagation). Now in order to
use this aspect, I need an interface (otherwise, no proxy can be
created). However, I have some methods on this class which I would
like to proxy which are public, some are protected, some are package.
Because of this stupid restriction, I have to make all of the methods
public, or do ridiculous things with protection on inner classes.

The problem might not be the interface specification,
but the way interfaces are used by the proxy specification.

A proxy could use several interfaces, one for public methods,
one for private methods. But »private« to whom?

Privacy is a static aspect, related to the way the source
code is organized into classes and packages. An object does
not have a scope, only lifetime. The compiler checks privacy
at compile time. At runtime, there is no privacy, because
there is no scope (like, e.g., a package). Proxies often are
dynamic entities created at run time. So the whole concept
of privacy might not apply here.

However, the JLS does not define »aspect« nor »proxy« IIRC,
so when using these words, you need to give the library
whose dictionary is to be used, when interpreting the words
»aspect« and »proxy«.
 
S

Stefan Ram

at compile time. At runtime, there is no privacy, because
there is no scope (like, e.g., a package). Proxies often are

The above might not be true in Java.
I was thinking about OOP in general.
 
V

Volker Borchert

Joshua said:
You can use abstract classes where reasonable;

No, you can't, at least in some cases, because Java does not support
multiple inheritance... and there are cases where the memory overhead
of a Delegate is not tolerable.
 
J

Joshua Cranmer

No, you can't, at least in some cases, because Java does not support
multiple inheritance... and there are cases where the memory overhead
of a Delegate is not tolerable.

I said "where reasonable" did I not? I know that multiple inheritance
renders flaws in using abstract classes, etc., etc., etc... but, given
the little I know of this use case, abstract classes seem like a
feasible way to go.
 
O

Owen Jacobson

I think the original Java design underestimated the extreme usefulness
of Java interfaces. At the time one of their uses, representing the
public face of a package, was assumed to be the only possible use.

I've wanted to use intra-package interfaces, containing only default
access methods. There is an unpleasant choice between making something
that should be an interface into an abstract class or having public
methods that are supposed to only be used within one package.

As Stefan pointed out, interfaces themselves don't have to be public.
This is legal:

package com.example;

interface SomeInternalAbstraction {
public void flog(Horse horse);
}

-o
 
S

Stefan Ram

Owen Jacobson said:
As Stefan pointed out, interfaces themselves don't have to be public.

IIRC, I did not write this, but thought about whether to write it.
So it seems that you must have read my mind!
 
R

Roedy Green

Could someone please explain to me the rational behind only allowing
public methods on interfaces? In my mind, protection and interfaces
are two independent if perhaps somewhat related concepts.

Interfaces are for gluing things together that have different
ancestries. If you could specify that at interface were package
scope, which you would limit all implementors to being in the
interface's package. In that case, you might as well use an abstract
class.

I too have often wanted non-public methods in interfaces, but that is
a possible rationale why they are always public.
 
E

Esmond Pitt

If you could specify that at interface were package
scope

.... which you can ...

, which you would limit all implementors to being in the
interface's package.

.... which again you can.
In that case, you might as well use an abstract
class.

Or an interface.
I too have often wanted non-public methods in interfaces, but that is
a possible rationale why they are always public.

It doesn't have anything to do with it. Interfaces themselves can be
specified without an access modifier, which gives them package access;
and nested interfaces can have any of the access modifiers.

The OP is asking about the access to what is *inside* the interface.
 
T

Tom Anderson

Could someone please explain to me the rational behind only allowing
public methods on interfaces? In my mind, protection and interfaces
are two independent if perhaps somewhat related concepts.

For instance, I have an aspect which creates a proxy of a given
interface (which handles transaction propagation). Now in order to
use this aspect, I need an interface (otherwise, no proxy can be
created). However, I have some methods on this class which I would
like to proxy which are public, some are protected, some are package.
Because of this stupid restriction, I have to make all of the methods
public, or do ridiculous things with protection on inner classes.

There are other examples, too. In fact one could imagine a case where
one would only want protected methods on an interface.

Do you have any examples of this problem that don't involve the horrific
crime against nature that is aspect-oriented programming?

tom
 
S

Stefan Ram

public InterfaceB getPrivateInterface( privateClassA token );

[amendment: »privateClassA« should have been written
with an uppercase »P«.]

Or, a hack as a last ressort:

If one has a public method in InterfaceA such as

public ... methodA( ..., SomeClassA object, ... );

in the interface, and SomeClassA is not final, we can
extend »SomeClassB« by a private class »PrivateClassA«.

The method »methodA« will check at run time, whether »object«
is of this private class »PrivateClassA«. If so, it will call
a method from »PrivateClassA«:

object.acceptPrivateInterface( myPrivateInterfaceObject )

so that now the caller has a reference to the private
interface object.

The hack is not visible in the public interface InterfaceA
and it is impossible for a client out of the scope of
»PrivateClassA« to observe this behavior as long as the
implementation does not release such a token object to the
outside. While this is not documented in »InterfaceA« nor
»methodA«, it could be documented in »PrivateClassA« and
of course in the source code of »methodA« via Java comments.
 
M

Mike Schilling

Patricia Shanahan said:
The really unfortunate decision is not the public methods only, but the
decision to make non-specification of access mean public interface
method declarations but package access in class method declarations.
That cuts off any possibility of changing interfaces now to make them
more flexible.

Unless new syntax like "package-private" is introduced.
 
M

Mike Schilling

Patricia Shanahan said:
The really unfortunate decision is not the public methods only, but the
decision to make non-specification of access mean public interface
method declarations but package access in class method declarations.
That cuts off any possibility of changing interfaces now to make them
more flexible.

Actually, you could make an argument that "protected" on an interface method
would mean "only visible within the package", because it can't mean "and
also visible to derived types".
 
T

Tom Anderson

Actually, you could make an argument that "protected" on an interface
method would mean "only visible within the package", because it can't
mean "and also visible to derived types".

It could mean 'visible to types derived from implementors of the
interface'. It would mostly act to constrain the access modifier on the
implementing method.

If you interpreted interface-protected your way, you would have to permit
implementors to declare their implementations package-access, otherwise it
would be pointless, and that would mean that you would be writing
implementations that appeared to have a narrower access modifier than
their specification.

In code:

package x;

public interface I {
protected void m();
}

public class A implements I {
protected void m() {} // legal, looks normal, but widens access!
}

public class B implements I {
/*package*/ void m() {} // is this legal?
}

package y;

class C extends x.A {
void foo() {
m(); // i probably shouldn't be able to do this
I i = this;
i.m(); // i won't be able to do this
}
}

Which is why ...

Unless new syntax like "package-private" is introduced.

That seems like a very good idea. Indeed, a future revision of the
language could do that, and at the same time deprecate the omission of an
access modifier altogether.

What i'd really like to see is a slightly more complicated but much more
expressive system of access control. I worked this out with a friend a
while ago, and i think the model should be:

1. The universe consists of a tree of things: the leaves are features
(fields and methods), and the branches are containers (packages and
classes - classes are also features in some ways, and i don't think that
causes any difficulty), with the root being the default package. Packages
can contain packages and classes; classes can contain classes and
features.

2. Every feature explicitly exposes itself at one scope; it is visible to
any code defined within that scope, including nested scopes. 'public'
means it is exposed to the default package. 'private' means that it is
exposed to the outermost enclosing class. This is as now. A new modifier
'package' means that it is exposed to the innermost enclosing package.
This differs from the current default in that it is visible to subpackages
(the current default is not visible in subpackages, although it is visible
in nested classes in the same package). The lack of an explicit modifier
would elicit a compiler warning, and be treated the same as 'package'
(this widens access to these features, but in a backwards-compatible way).

3. In addition to these simple modifiers, it is possible to explicitly
specify an exposure scope - this can be any scope enclosing the feature.
The syntax i would use would be 'private(name.of.scope)'. 'public' is thus
shorthand for 'private()', 'package' is shorthand for
'private(innermost.enclosing.package)', and 'private' is shorthand for
'private(outermost.enclosing.class)'. The scope name is resolved in the
usual way, so scopes which are classes would not need to be fully
qualified.

4. In addition to the exposure scope, a feature can be made visible to
subclasses of its defining class, whatever package they may be in. This is
done by replacing 'private' with 'protected'; this accepts an explicit
scope in the same way as 'private'. The natural exposure scope for an
unqualified 'protected' would be the same as for an unqualified 'private',
ie the outermost enclosing class, but this would break backwards
compatibility, so sadly, it must mean
'protected(innermost.enclosing.package)'. Perhaps we should allow a
shorthand for the outermost enclosing class, perhaps 'this', so you could
write 'protected(this)' to allow access only to subclasses and inner
classes.

The main thing that this gives you is a way to make features visible
across packages in a hierarchy. This is a frequent problem in large
projects which are intended to be modules in a larger world (eg on a vast
project, or libraries for public consumption); a class in org.foo.io might
need to be visible to one in org.foo or org.foo.core, but should not be
visible to unrelated code in com.bar. Similarly, methods in a class in
org.foo often need to be accessible to classes in org.foo.io, but not
com.bar. At present, you end up with public methods marked 'PRIVATE API,
DO NOT USE', which is total rubbish. The proposed access system would let
you scope all these methods to org.foo, and have them visible to
everything in the project.

What it no longer lets you do is have things in org.foo that are *not*
visible throughout the project. However, i would suggest that such things
really belong in a subpackage. The parent package should be minimal, and
only contain things for general consumption.

It also lets you have features which are visible to subclasses but not the
rest of the package, which is something i have always wanted.

If we extend the explicit scope notation to accept multiple exposure
scopes, then we have essentially copied the C++ friend mechanism. That
would let me solve the classic JPA problem of how i stop unrelated classes
calling the internal-use-only innerWhatever methods in this scenario (this
is actually a slight variation in the classic pattern, but i hope it's
clear):

@Entity
public class Department {
@OneToMany(mappedBy="dept")
private List<Employee> employees;

public void addEmployee(Employee emp) {
emp.setDepartment(this);
}

public void removeEmployee(Employee emp) {
emp.setDepartment(null);
}

void innerAddEmployee(Employee emp) {
employees.add(emp);
}

void innerRemoveEmployee(Employee emp) {
employees.remove(emp);
}
}

@Entity
public class Employee {
@ManyToOne
private Department dept;

public void setDepartment(Department dept) {
if (this.dept != null) this.dept.innerRemoveEmployee(this);
if (dept != null) dept.innerAddEmployee(this);
this.dept = dept;
}
}

At the moment, the methods have to be at least package-access, because
Employee needs to be able to call them. But with the proposed mechanism, i
could declare them:

private(Employee) void innerAddEmployee(Employee emp)
private(Employee) void innerRemoveEmployee(Employee emp)

And access would be restricted to just where they were needed.

Compared to C++'s friendship system (which i don't understand well, so
correct me if i'm wrong), we have finer-grained control over what is
exposed (individual features, rather than all the features in the class),
but coarser-grained control over who we expose it to (classes, rather than
individual methods). The former is clearly better, because it means we can
expose the things we need to, whilst keeping most details of the class
encapsulated. I would argue that the latter is also better, because the
exposing class has no business knowing which particular methods of the
friend class are going to make use of the exposure; in the above example,
i want to be free to refactor the calls from Employee to Department.inner*
into a separate method (perhaps updateDepartmentEmployeeLists), without
having to modify Department (particularly because it might be a private
method - in which case in C++, Department would have to know about a
private method of Employee!).

tom
 
S

Stefan Ram

I want to give an example for what I was thinking about:

Two compilets (aka SSCCEs):

First: Make some methods of the interface callable only from
a certain scope in a way so that calls from other scopes
will be refuted already at compile time.

Second: Add undocumented behavior to a public class so that
the access can be obtained from a certain scope only by
passing a private key object at runtime.

First: Method »example« can call »method( Key )«, while
Method »main« can't:

class Example
{
public static interface PublicInterface
{ public void method();
public /* private intended */ void method( Key parameter ); }

public static class Implementation implements PublicInterface
{
public void method()
{ java.lang.System.out.println( "public" ); }

public void method( final Key parameter )
{ java.lang.System.out.println( "private" ); }}

/* This is the key for access to the private Interface */
private static final class Key {}

public static void example()
{
/* Can get direct access to method( Key ) from here. */
Example.PublicInterface publicInterface = new Example.Implementation();
publicInterface.method( new Example.Key() ); }}

public class Main
{ public static void main( final java.lang.String[] args )
{
/* Can't get direct access to method( Key ) from here. */
Example.PublicInterface publicInterface = new Example.Implementation();
publicInterface.method();
Example.example(); }}

/* prints:
public
private
*/

Second: Method »example« can call »method( Key )«, while
Method »main« can't:

interface PublicInterface
{ public void method( java.lang.Object parameter ); }

class Example implements PublicInterface
{
private interface PrivateInterface
{ public void privateMethod(); }

private static class PrivateImplementation implements PrivateInterface
{ public void privateMethod()
{ java.lang.System.out.println( "private" ); }}

final private PrivateImplementation privateImplementation =
new PrivateImplementation();

/* This is the key for access to the private Interface */
private static class Acceptor
{ private PrivateInterface privateInterface;
private void accept( final PrivateInterface privateInterface )
{ this.privateInterface = privateInterface; }
private PrivateInterface get()
{ return this.privateInterface; }}

@java.lang.Override
public void method( final java.lang.Object parameter )
{ if( parameter instanceof Acceptor )
{ final Acceptor acceptor =( Acceptor )parameter;
acceptor.accept( privateImplementation ); }
else
{ java.lang.System.out.println( "public" ); }}

public static void example()
{
/* Can get direct access to PrivateInterface from here. */
final PublicInterface publicInterface = new Example();
final Acceptor acceptor = new Acceptor();
publicInterface.method( acceptor );
PrivateInterface privateInterface = acceptor.get();
privateInterface.privateMethod(); }

}

public class Main
{
public static void main( final java.lang.String[] args )
{
/* Can't get direct access to PrivateInterface from here. */
PublicInterface publicInterface = new Example();
publicInterface.method( null );
( ( Example )publicInterface ).example( ); }}

/* prints:
public
private
*/
 
T

Tom Anderson

I want to give an example for what I was thinking about:

Two compilets (aka SSCCEs):

First: Make some methods of the interface callable only from
a certain scope in a way so that calls from other scopes
will be refuted already at compile time.

[snip]

public class Main
{ public static void main( final java.lang.String[] args )
{
/* Can't get direct access to method( Key ) from here. */

Yes you can:

publicInterface.method(null);

For this technique to be effective, there has to be a null check in the
method. Even then, it will be a runtime error, not a compile-time error,
when it is called from outside the intended scope.

Your second technique does work, though, because it requires the caller to
be able to provide an instance of the hidden Acceptor type. Another way of
using that, which i think gives you static safety, is:

public class PublicFace {
public class PrivateFace { // intended private
public void secret() {}
}
private PrivateFace hyde = new PrivateFace();
private static class Extractor {
public static final Extractor THIS = new Extractor();
public PrivateFace extract(PublicFace jekyll) {
return jekyll.hyde;
}
}

public static void insider(PublicFace jekyll) {
Extractor.THIS.extract(jekyll).secret();
}
}

public class Main {
public static void outsider(PublicFace jekyll) {
// i claim that there is no way to write an expression of type Extractor here
// without that, you cannot possibly extract hyde from jekyll
}
}

tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top