Why only public methods on interfaces?

Discussion in 'Java' started by kramer31, Apr 8, 2011.

  1. kramer31

    kramer31 Guest

    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.
    kramer31, Apr 8, 2011
    #1
    1. Advertising

  2. On 11-04-07 09:09 PM, kramer31 wrote:
    > 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
    Arved Sandstrom, Apr 8, 2011
    #2
    1. Advertising

  3. On 04/07/2011 08:09 PM, kramer31 wrote:
    > 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.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
    Joshua Cranmer, Apr 8, 2011
    #3
  4. kramer31

    Stefan Ram Guest

    kramer31 <> writes:
    >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«.
    Stefan Ram, Apr 8, 2011
    #4
  5. kramer31

    Stefan Ram Guest

    -berlin.de (Stefan Ram) writes:
    >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.
    Stefan Ram, Apr 8, 2011
    #5
  6. Joshua Cranmer wrote:
    > 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.

    --

    "I'm a doctor, not a mechanic." Dr Leonard McCoy <>
    "I'm a mechanic, not a doctor." Volker Borchert <>
    Volker Borchert, Apr 8, 2011
    #6
  7. On 04/07/2011 10:43 PM, Volker Borchert wrote:
    > Joshua Cranmer wrote:
    >> 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.


    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.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
    Joshua Cranmer, Apr 8, 2011
    #7
  8. On 2011-04-08 00:49:02 -0400, Patricia Shanahan said:

    > On 4/7/2011 5:09 PM, kramer31 wrote:
    >> 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.

    >
    > 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
    Owen Jacobson, Apr 8, 2011
    #8
  9. kramer31

    Stefan Ram Guest

    Owen Jacobson <> writes:
    >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!
    Stefan Ram, Apr 8, 2011
    #9
  10. kramer31

    Roedy Green Guest

    On Thu, 7 Apr 2011 17:09:51 -0700 (PDT), kramer31
    <> wrote, quoted or indirectly quoted
    someone who said :

    >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.
    --
    Roedy Green Canadian Mind Products
    http://mindprod.com
    Doing what the user expects with respect to navigation is absurdly important for user satisfaction.
    ~ anonymous Google Android developer
    Roedy Green, Apr 8, 2011
    #10
  11. kramer31

    Esmond Pitt Guest

    On 8/04/2011 8:18 PM, Roedy Green wrote:
    > 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.
    Esmond Pitt, Apr 8, 2011
    #11
  12. kramer31

    Tom Anderson Guest

    On Thu, 7 Apr 2011, kramer31 wrote:

    > 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

    --
    the logical extension of a zero-infinity nightmare topology
    Tom Anderson, Apr 8, 2011
    #12
  13. kramer31

    Stefan Ram Guest

    -berlin.de (Stefan Ram) writes:
    >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.
    Stefan Ram, Apr 9, 2011
    #13
  14. "Patricia Shanahan" <> wrote in message
    news:...
    >
    > 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.
    Mike Schilling, Apr 10, 2011
    #14
  15. "Patricia Shanahan" <> wrote in message
    news:...
    >
    > 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".
    Mike Schilling, Apr 10, 2011
    #15
  16. kramer31

    Tom Anderson Guest

    On Sat, 9 Apr 2011, Mike Schilling wrote:

    > "Patricia Shanahan" <> wrote in message
    > news:...
    >
    >> 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".


    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 ...

    On Sat, 9 Apr 2011, Mike Schilling wrote:

    > 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

    --
    A military-industrial illusion of democracy
    Tom Anderson, Apr 10, 2011
    #16
  17. kramer31

    Stefan Ram Guest

    -berlin.de (Stefan Ram) writes:
    >-berlin.de (Stefan Ram) writes:
    >>A proxy could use several interfaces, one for public methods,
    >>one for private methods. But »private« to whom?

    >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
    */
    Stefan Ram, Apr 10, 2011
    #17
  18. kramer31

    Tom Anderson Guest

    On Sun, 10 Apr 2011, Stefan Ram wrote:

    > -berlin.de (Stefan Ram) writes:
    >> -berlin.de (Stefan Ram) writes:
    >>> A proxy could use several interfaces, one for public methods,
    >>> one for private methods. But »private« to whom?

    >> 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

    --
    I am the best at what i do.
    Tom Anderson, Apr 10, 2011
    #18
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Charles A. Lackman
    Replies:
    1
    Views:
    1,330
    smith
    Dec 8, 2004
  2. SpamProof
    Replies:
    0
    Views:
    534
    SpamProof
    Oct 21, 2003
  3. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,769
    Smokey Grindel
    Dec 2, 2006
  4. Replies:
    26
    Views:
    770
  5. Robert
    Replies:
    16
    Views:
    186
Loading...

Share This Page