|
Quick Lists
|
|
Bug ID:
|
4456057
|
|
Votes
|
7
|
|
Synopsis
|
package access for interface methods
|
|
Category
|
java:specification
|
|
Reported Against
|
1.3
, 1.2rc2
|
|
Release Fixed
|
|
|
State
|
6-Fix Understood,
request for enhancement
|
|
Priority:
|
5-Very Low
|
|
Related Bugs
|
4144491
,
4230610
|
|
Submit Date
|
08-MAY-2001
|
|
Description
|
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)
Interfaces are very useful, but I often want to write methods that have package
(default) access instead of public access.
For example, I have a viewer class that can place any one of many custom
components in its main view. The viewer then asks this newly-added component
which menu items should be enabled. This provides a simple, powerful
implementation of context-sensitive menus. I do this through an interface, which
all the components implement. For example, the interface could look like this:
package com.myfirm.mywidget.ui;
import java.awt.Component;
interface MenuStates // interface has package access
{
Component getViewer(); // I want these methods to have package access, too
boolean isViewEnabled();
boolean isCopyEnabled();
boolean isSortEnabled();
...
}
Any class that implements this can provide a viewer for my main window. However,
there is no reason why any of these methods need to be visible outside the
current package. I want to encapsulate them inside the package, and I especially
want to hide the getViewer method. The current specification for Java doesn't
allow this.
I can't achieve this through an abstract class, as the evaluator of 4144491
suggests, because the classes that implement MenuStates all extend other AWT
classes. These methods need to be in an interface.
Please don't close this as a duplicate of 4144491. That was asking for protected
access, which is clearly not a customer idea. Package access is different. It's
essentially a limited version of public access. Methods should only be allowed
to have package access if the interface itself has package access. A public
interface should certainly require public methods. But right now, I can write an
interface with package access, but I'm forced to give its methods public access.
This makes no sense.
(Review ID: 124020)
======================================================================
|
|
Work Around
|
N/A
|
|
Evaluation
|
There is a logic to this proposal, but it has downsides as well.
1. Package access is in fact quite problematic in some ways, and extending
its reach is not really that attractive.
2. This isn't easy to fix. It requires VM support in order to work.
I am certain that this can be worked around in various ways, which may
require changing the design a bit.
We should take this under consideration.
xxxxx@xxxxx 2001-05-08
The Java Module System introduces module-private accessibility for interface members. This is arguably more useful than package-private accessibility, since it means classes in arbitrary packages within the interface's module can implement the interface. (Important if packages are refactoring from one module to another with any degree of frequency.) Having said that, it would not be difficult to permit 'package' as a modifier on interface members, and for that matter class members too.
Posted Date : 2008-07-24 01:31:14.0
|
|
Comments
|
Submitted On 31-JAN-2002
murrayla
I have not actually hit this problem (yet) but I think it
would be a good idea. It seems illogical to have been
given package level access for classes/interfaces but nto
for their methods.
Submitted On 06-JUL-2002
thomas-beck
I fully agree with MiguelM.
When an interface is non public, it is absurd to require the
implemented methods to be public.
I believe that James Gosling missed his breakfast on that
day :-)
As soon your packages grows, good design requires non public
interfaces to decouple some of your classes each to the
other, even inside a same package.
But promoting your internal methods to 'public' is of course
not acceptable.
Of course we can avoid to use package-level interfaces to
reference classes internally, but that reduces the quality
of the design.
Would you like to see a magazine explaining why Java does
not allow as good design as other OO languages do ?
Submitted On 14-AUG-2002
shrink_laureate
Yes.
Submitted On 21-APR-2009
I encountered a similar design challenge with one of my projects. I wanted to define a listener interface which could be implemented by various objects within my package. The problem was that the subject of
the listener (think property for a propertychangelistener) didn't have scope outside of the package. Given that the listener interface defined callbacks that were executed for various events, it was
dangerous to allow access to those methods to escape the package. The original approach was similar to the following:
interface BlahListener //Package level visibility...
{
void blahEvent1(); //Ideally, package level visibility due to the potentially serious issues that could arise if called outside the design context
void blahEvent2(); //Ideally, package level visibility due to the potentially serious issues that could arise if called outside the design context
}
//This defines an abstract class thatis subclassed outside of the package.
public abstract class X extends T implements This, That, BlahListener
{
void method1() {}
void method2() {}
///...
void methodN() {}
public void blahEvent1() //Because this is public now (due to enforcement within the interface), this can be called outside of the package!
{
//Do something...
}
public void blahEvent2()
{
//Do something else...
}
}
public final class SomeAPIClass
{
void addBlahListener(BlahListener listener)
{
//Add...
}
void removeBlahListener(BlahListener listner)
{
//Remove...
}
void performAction( ? extends X var)
{
addBlahListener(var);
//Do something that could effect blah, forcing a callback to X...
removeBlahListener(var);
}
}
The solution to the problem that I chose was to define an inner class and methods to enforce package-level access to the ChannelListener object. This fix, in the context of the above code, would look like
this:
public abstract class X extends T implements This, That //We have removed implementation of the BlahListener interface
{
private final BlahListener listener = new ListenerCallBackClass(); //ListenerCallBackClass is defined below
void method1() {}
void method2() {}
///...
void methodN() {}
private final blahEvent1Stuff()
{
//Place code for blahEvent1 from original solution here...
}
private final blahEvent2Stuff()
{
//Place code for blahEvent2 from original solution here...
}
BlahListener getBlahListenerObject() //Because this method is package-level access, then we can effectively limit access to the callback methods to the package level
{
return listener;
}
private final class ListenerCallBackClass implements BlahListener
{
public void blahEvent1()
{
X.this.blahEvent1Stuff();
}
public void blahEvent2()
{
x.this.blahEvent2Stuff();
}
}
}
public final class SomeAPIClass
{
void addBlahListener(BlahListener listener)
{
//Add...
}
void removeBlahListener(BlahListener listner)
{
//Remove...
}
void performAction( ? extends X var)
{
addBlahListener( var.getBlahListenerObject() ); //Modified this to be a call to the package-level method for retrieving the inner class
//Do something that could effect blah, forcing a callback to X...
removeBlahListener( var.getBlahListenerObject() );
}
}
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|
|
|
 |