Protected and package in iterface

P

Philipp

Lew wrote in thread "Interface":
> What maxnesler forgot to show is that the implementing class declares
> the method to be 'public', which is implied automatically in the
> interface declaration

Why did the people writing the Java specs decide that an interface
should not contain protected and package methods?

I can imagine several cases where this would be useful.

Phil
 
L

Lew

Philipp said:
Lew wrote in thread "Interface":

Why did the people writing the Java specs decide that an interface
should not contain protected and package methods?

I can imagine several cases where this would be useful.

Then you want abstract classes - they are like interfaces in that they cannot
be instantiated, but unlike in that they can contain implementation.

The whole idea of an interface is that it's pure public contract. Including
(package-)private or protected methods or, indeed, any implementation just
isn't part of what it's for.

Perhaps you can describe what such a feature in an interface would give you
that isn't available from the existing mechanisms?
 
R

Roedy Green

Why did the people writing the Java specs decide that an interface
should not contain protected and package methods?

I think the original idea was interfaces were invented to allow people
to write code without having access to any existing implementation,
just the "blueprints". They would allow strangers to plug in their
code into yours. This necessarily meant public.

After there were invented, I think it came clear they have wider use,
but by then it was too late to allow scope modifiers.

see http://mindprod.com/jgloss/interface.html

I describe them as the "duct tape" of Java.
 
J

Joshua Cranmer

Philipp said:
Why did the people writing the Java specs decide that an interface
should not contain protected and package methods?

I can imagine several cases where this would be useful.

Let me point out that there are two separate uses of interfaces in Java:
1. An interface à la the ones defined by IDL.
2. A replacement for function pointers.

In the first case, anything other than public accessors and constant
values are pointless. The interface is describing how the conforming
implementation must provide its public API; anything not related to this
external API is not provided, giving the implementor free choice to
decide how to implement as long as it faithfully fulfills the contracts
of the interface API. org.w3c.dom is, IMHO, the best example of when an
interface is used in this sense.

The second case merely arises out of two thorns in the Java programming
language: the lack of pointers to functions, and the impossibility of
multiple inheritance. java.awt.event is the prime example of the use of
interfaces as callbacks--the methods are not "I will do XXX if you call
me" but "call me if you do XXX". Arguably, the use of protected and
package-private methods are feasible here, but keeping strictly to the
idea of callback should eliminate much of the need. I would be in favor
of a mechanism to not advertise the implementation of an interface, but
I do not see how that could be feasible (C++'s public/protected/private
inheritance doesn't fit the model here).

Judging from the name of the keyword, I am guessing--I repeat, this is
only a guess--that an interface was originally designed for the first
flavor and that the second flavor was brought about at a bout of
simplification of the language towards the end of the initial process.
 
P

Philipp

Lew said:
Perhaps you can describe what such a feature in an interface would give
you that isn't available from the existing mechanisms?

Multiple inheritance inside a package for example. You develop a
package, and internally you want your classes to implement some
interface. But you don't want those methods to be public, just package
visible.
You don't want to let the outside world know about the internal
functioning of your lib/package (there's a public API for that), but
still want to have the power of the interface construct when developping
the lib.

Phil
 
L

Lew

Philipp said:
Multiple inheritance inside a package for example. You develop a
package, and internally you want your classes to implement some
interface. But you don't want those methods to be public, just package
visible.
You don't want to let the outside world know about the internal
functioning of your lib/package (there's a public API for that), but
still want to have the power of the interface construct when developping
the lib.

So make the interface itself package-private, or nest it and declare it any
access level you want. Doesn't that do what you need?
 
T

tam

So make the interface itself package-private, or nest it and declare it any
access level you want. Doesn't that do what you need?


While I think that keeps knowledge of the interfaces from the public,
the requirement that methods be public makes it hard to hide those.

E.g., in package 'vehicles' we have interfaces Serviceable and
Warranteeable with methods service and warrantee that should only be
used within the package. The interfaces are declared with package
visibility. We create a public class Car (in vechicles) which
implements these interfaces. If I now create an instance of Car and
use it outside the package, I can't cast it explicitly to Serviceable
or Warranteeable, but I can access the service and warrantee methods.

So to use interfaces I need to break encapsulation. When I tested
this I found even the interfaces are pretty visible. E.g., if I try

System.out.println("Try to access
interface:"+
Class.forName("vehicles.Serviceable").isInstance(car));

to the Tester class below, it runs fine (and prints true). An
explicit use of instanceof will fail in compilation.

Regards,
Tom McGlynn


Code for above:
public class Tester {

public static void main(String[] args) {

Car car = new Car();
car.service();
car.warrantee();
}
}
----
package vehicles;
public class Car implements Serviceable, Warranteeable {

public void service() {
System.out.println("Service called");
}
public void warrantee() {
System.out.println("warrantee called");
}
}
 
J

Joshua Cranmer

>
While I think that keeps knowledge of the interfaces from the public,
the requirement that methods be public makes it hard to hide those.

E.g., in package 'vehicles' we have interfaces Serviceable and
Warranteeable with methods service and warrantee that should only be
used within the package. The interfaces are declared with package
visibility. We create a public class Car (in vechicles) which
implements these interfaces. If I now create an instance of Car and
use it outside the package, I can't cast it explicitly to Serviceable
or Warranteeable, but I can access the service and warrantee methods.

While not quite the same thing, this should be sufficient:

public class Car {
class PackageView implements Serviceable, Warranteeable {
// Methods, etc.
}

PackageView getPackageView() {
return new PackageView();
}
}

It's a cheap-ish hack, but it does a fair job of emulating C++'s
protected or private inheritance.
 
T

tam

While not quite the same thing, this should be sufficient:

public class Car {
class PackageView implements Serviceable, Warranteeable {
// Methods, etc.
}

PackageView getPackageView() {
return new PackageView();
}

}

It's a cheap-ish hack, but it does a fair job of emulating C++'s
protected or private inheritance.

I'm sure there are ways to get around this but it seems like a lot of
work. E.g., wouldn't this mean that I need to define a PackageView
class inside each vehicle type (Bicycle, Trolley, Boat...)? It does
seem a bit hackish to me... It seems to obfuscate what would be a
straightforward inheritance tree.

In practice this hasn't been a real issue for me, but I tend to write
code with rather simple class relationships and I probably make too
much public anyway.

Regards,
Tom McGlynn
 
L

Lew

I'm sure there are ways to get around this but it seems like a lot of
work. E.g., wouldn't this mean that I need to define a PackageView
class inside each vehicle type (Bicycle, Trolley, Boat...)? It does
seem a bit hackish to me... It seems to obfuscate what would be a
straightforward inheritance tree.

Whatever. It took me about 15 minutes to work up this SSCCE in 3 files:

// testit/InnerFace.java
package testit;

/* p-p */ interface InnerFace
{
public void foo();
}

// testit/Fimpl.java
package testit;

/** Fimpl - .
*/
public class Fimpl implements Runnable
{
/** Keep the interface on the down-low.
*/
/* p-p */ static class NestedFimpl implements InnerFace
{
@Override
public void foo()
{
System.out.println( "NestedFimpl.foo()" );
}
}

private volatile InnerFace face;

/** No-arg constructor.
*/
public Fimpl()
{
this( null );
}

/* p-p */ Fimpl( InnerFace f )
{
face = (f == null? new NestedFimpl() : f);
}

/* p-p */ void setFace( InnerFace f )
{
face = (f == null? new NestedFimpl() : f);
}

/* p-p */ InnerFace getFace()
{
return face;
}

/** Delegate an action to <code>foo()</code>.
*/
@Override
public void run()
{
face.foo();
}

/** Main method.
* @param args <code>String []</code> program arguments.
*/
public static void main( String[] args )
{
Fimpl fimpl = new Fimpl();
fimpl.getFace().foo();
fimpl.run();
fimpl.setFace( new InnerFace()
{
@Override
public void foo()
{
System.out.println( " AnonyFace.foo()" );
}
});
fimpl.run();
}
}

// testit/other/TestFimpl.java
package testit.other;

import testit.Fimpl;

/** TestFimpl - .
*/
public class TestFimpl
{
/** Main method.
* @param args <code>String []</code> program arguments.
*/
public static void main( String [] args)
{
Fimpl fimpl = new Fimpl();
// InnerFace face = fimpl.getFace(); // not enough access rights
fimpl.run();
}
}
 
T

tam

Whatever. It took me about 15 minutes to work up this SSCCE in 3 files:
....
Lew

Well I'm not sure whether you're trying to support or refute my
point. To me the code posted seems to support it, in the sense that
it conceals the relationship between the classes and interfaces, i.e.,
here that a Fimpl has the capabilities of an InnerFace. It does allow
that capability to be hidden from the public which is great, but it
seems less clean, clear and flexible than what would be possible if
interfaces could have non-public methods, which is where this thread
started. As always workarounds are possible, but there seems to be a
real cost in this restriction on interface methods, and I've not seen
a corresponding benefit.

Not that things are going to change. Since the language spec allows
(and conventions encourage) coders to drop the public qualifier on
interface methods, allowing non-public methods in interfaces would
break vast amounts of existing code.

Regards,
Tom McGlnn
 
L

Lew

Well I'm not sure whether you're trying to support or refute my
point. To me the code posted seems to support it, in the sense that
it conceals the relationship between the classes and interfaces, i.e.,

Which is what you asked for.
here that a Fimpl has the capabilities of an InnerFace. It does allow
that capability to be hidden from the public which is great, but it
seems less clean, clear and flexible than what would be possible if

"Seems" is such a weasel word. In this case, it means that you are resisting
the idiomatic Java way of doing things because you want your own internal
ideal language. Java ain't that, so learn to live with Java's way.
interfaces could have non-public methods, which is where this thread
started. As always workarounds are possible, but there seems to be a
real cost in this restriction on interface methods, and I've not seen
a corresponding benefit.

It's not a real cost, it's one you made up.

My point is that there isn't any complexity or difficulty to the idiom. It
only took about 15 minutes to work up that example. Come on! How hard is that?

To anyone used to reading Java, the code is hardly complex at all. Just
because you think it looks hairy doesn't make Java's way bad. Get used to
Java and it'll look a lot better to you.

It's a poor workman who blames his tools.
 
L

Lew

As always workarounds are possible, but there seems to be a
real cost in this restriction on interface methods, and I've not seen
a corresponding benefit.

This was no "workaround". The only difference between what Java does and what
you want is that Java makes the whole interface, say, package-private. That
does exactly what you want, make the methods of that interface available only
to the package, with less code than if one had to mark every method.

It also keeps the self-documenting nature of 'interface' intact - that an
interface defines the public face to a type, the part others can see. If
that's not what you mean to do, then an interface is the wrong thing to use.
Private, package-private and protected methods exist for the purpose of
implementation, yes, implementation, not contract, and therefore belong in a
class, for you, an abstract class, as was stated waaay upthread.

It would be silly and damaging to specify implementation in an interface.
It's against their very raison d'être.

My code points out how very easy it is - easy! - to contain the effects of an
interface to package level, using three different common Java idioms - a
top-level type declaration, a nested type declaration, and an anonymous inner
declaration. All three idioms effortlessly contained their effects to package
level in a way that you call a "real cost", "restriction", and that you have
"not seen a corresponding benefit".

The cost is zero. The benefit is that interfaces perform their architectural
role of specifying a contract, only, and that their effect can be contained to
arbitrary levels of protection so transparently that you misd-attribute the
complexity of an inner-class declaration to the lack of containment of the
interface. The interface was so well contained that its contained nature was
invisible to you. It really doesn't get any more effortless than that.

Unlike your approach, where one has to wonder method by method what the
containment level is. Java's approach is much simpler, to the point where the
effort vanishes altogether.
 
T

tam

Which is what you asked for.
[Seem to have lost the first version of this... Apologies if this
comes twice.]

There are a couple of meanings of conceal that are relevant here and
perhaps I should have been clearer. It is good that the interfaces
and methods are not visible to the public. However it is not good
that the relationship between the classes and interfaces is obscured
in the code and harder to use for those coding within the package.

E.g., which of these expresses the relationship between classes and
interfaces more clearly:

class Car implements Serviceable {...}

or

class Car {
class ServiceDelegate implements Serviceable {...}
Serviceable delegate = new ServiceDelegate()

I find the first a lot clearer but the second is required to hide
interface methods from the public.

Similarly I find it easier and clearer to invoke
void someMethod(Sericeable item) {...}
as
someMethod(car)
rather than
someMethod(car.delegate)
or
someMethod(car.getServiceDelegate())

The relationship between Car and Serviceable is explicit in the former
approach and only implicit in the later. So it's a lot easier for a
reader to miss the relationship there. Java has a standard and simple
way to restrict visibility but it cannot be used as flexibly for
interfaces as, e.g., in abstract classes. The question in this thread
is "Why?".

It's perfectly feasible to things the later way, but I don't think
it's as clear. To me that is a real cost.

....
It's not a real cost, it's one you made up.


My point is that there isn't any complexity or difficulty to the idiom. It
only took about 15 minutes to work up that example. Come on! How hard is that?

To anyone used to reading Java, the code is hardly complex at all. Just
because you think it looks hairy doesn't make Java's way bad. Get used to
Java and it'll look a lot better to you.

It's a poor workman who blames his tools.

Well I guess it takes a long time since I've been coding in Java for
over a decade. More seriously I am not blaming Java. I am trying to
understand why a choice was made. So far I've not seen any obvious
reason why the choice to restrict interfaces to public methods was
made. I'd not be surprised to find that there is some excellent
technical reason, e.g., something involving runtime resolution of
methods or interface inheritance
but so far the discussion suggests the authors of the language may not
have thought about how interfaces might be useful in restricted
contexts. I'd be delighted if someone pointed out some other reason.
It would probably illustrate some aspect of language design with which
I'm not familiar.

Regards,
Tom McGlynn
 
M

Mark Space

Not that things are going to change. Since the language spec allows
(and conventions encourage) coders to drop the public qualifier on
interface methods, allowing non-public methods in interfaces would
break vast amounts of existing code.

I wonder if Sun could re-use the 'package' key-word to mean package
private. This would allow new interfaces to explicitly declare a
package private methods.

interface SomeInterface {
package someMethod();
}

To make things cleaner, I think I'd require public interfaces to have
only public methods, and 'package' interfaces to have only 'package'
methods. An interface with no 'package' modifier would default to the
current behavior.

interface PublicInterface [
someMethod(); // Defaults to public, package not allowed.
}

package interface PackageInterface {
anotherMethod(); // Defaults to package, public not allowed.
}
 
L

Lew

Mark Space wrote:
To make things cleaner, I think I'd require public interfaces to have
only public methods, and 'package' interfaces to have only 'package'
methods. An interface with no 'package' modifier would default to the
current behavior.

interface PublicInterface [

The absence of a keyword means package-private access.
someMethod(); // Defaults to public, package not allowed.
}

package interface PackageInterface {
anotherMethod(); // Defaults to package, public not allowed.
}

This buys nothing. The methods of a package-private interface are visible
only within the package anyway, so the current setup already accomplishes
this. In fact, the misnamed "PublicInterface" above would be exactly right
for such a thing with no new keywords needed.
 

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,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top