Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't access protected static inner classes of extended classes #1806

Closed
scabug opened this issue Mar 19, 2009 · 12 comments
Closed

Can't access protected static inner classes of extended classes #1806

scabug opened this issue Mar 19, 2009 · 12 comments
Assignees

Comments

@scabug
Copy link

scabug commented Mar 19, 2009

Given a Java class defined like this:

#!java
package com.example;

public abstract class Test{
       protected static class Inner{}
       protected abstract Inner getInner();
}

It is not possible to implement this class in Scala from another package:

Welcome to Scala version 2.7.3.final (OpenJDK Server VM, Java 1.6.0_0).
scala> import com.example.Test
import com.example.Test

scala> class Implementor extends Test{
    | import Test.Inner
    | def getInner:Inner = null
    | }
<console>:7: error: class Inner cannot be accessed in object com.example.Test
      def getInner:Inner = null
                   ^

This aside, Inner is not in scope as you would expect it to be:

scala> class Implementor extends Test{
    | def getInner:Inner = null
    | }
<console>:6: error: not found: type Inner
      def getInner:Inner = null
                   ^
@scabug
Copy link
Author

scabug commented Mar 19, 2009

Imported From: https://issues.scala-lang.org/browse/SI-1806?orig=1
Reporter: @jrudolph

@scabug
Copy link
Author

scabug commented Mar 31, 2009

@dragos said:
It's a well known limitation, and goes against the way Scala works: no static members. They can be simulated to a certain extent by objects. In this case, Inner is a member of object Test, which is not a superclass of Implementor, hence the error.

@scabug
Copy link
Author

scabug commented Mar 31, 2009

@milessabin said:
I'm going to be a pain and reopen this ... sorry.

We've worked around similar examples at the Scala/Java border previously and I think we should finish the job off properly. It's been on my TODO list to take a look at this myself, and I'd rather keep this bug open as a reminder that it really should be addressed at some point.

Unless you really do want to limit interoperability with Java in this area, in which case wontfix it again. But I think that would be a shame.

@scabug
Copy link
Author

scabug commented Mar 31, 2009

@paulp said:
I quite agree with miles (not that anyone asked.) Too much blood has been shed already to achieve java interoperability, I think it would be a mistake to write off the remaining cases. Granted some areas will never be satisfying (say, raw types) but protected statics are, unfortunate as it may be, still a part of the language and people will quite reasonably expect to be able to use them.

If people can't count on smooth interoperation with java, the case to be made for scala is very badly damaged.

@scabug
Copy link
Author

scabug commented Mar 31, 2009

@jrudolph said:
To put that into context: I ran into the problem when I tried to write some Android code. When implementing [http://developer.android.com/reference/android/widget/Filter.html android.widget.Filter] you'll have to return an instance of [http://developer.android.com/reference/android/widget/Filter.FilterResults.html Filter.FilterResults]. This class is a static protected inner class which cannot be accessed from Scala. I've spotted no other protected inner classes in Android yet.

The workaround is to create an abstract class in Java implementing the interface which wraps accesses to the inner class. One may then implement this abstract class from Scala.

In this particular case:

#!java
import android.widget.BaseAdapter;
import android.widget.Filter;

public abstract class MyFilter<T> extends Filter{
        private final BaseAdapter parent;
        public MyFilter(BaseAdapter parent) {
                this.parent = parent;
        }

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults res = new FilterResults();
                T value = getResult(constraint);
                res.values = value;
                res.count = countFromData(value);
                return res;

        }
        @Override
        protected void publishResults(CharSequence constraint, FilterResults res) {
                setData(res.count,(T) res.values);
                if (res.count == 0)
                        parent.notifyDataSetInvalidated();
                else
                        parent.notifyDataSetChanged();
        }
        protected abstract void setData(int count,T data);
        protected abstract int countFromData(T data);
        protected abstract T getResult(CharSequence constraint);
}

Hmm, I think I understand the problem: Scala interprets the Java class (Test resp. Filter) as a class and a companion object holding all the static members. So the easiest fix is not feasible - to allow implementing classes access to (protected) members of the companion object of the implemented class - because it would affect Scala code as well. So, could perhaps protected static inner classes not be interpreted as (non-static) member classes as well? (What's the use case of protected static inner classes of objects in Scala?)

BTW: Why does the import work, shouldn't that be disallowed as well?

@scabug
Copy link
Author

scabug commented Mar 31, 2009

@odersky said:
I disagree. We can never achieve 100% java interop without becoming Java. We are at 99.5% now, and the further we go, the more expensive in terms of feature creep things are going to become. Static protected members are, next to raw types, the most ugly, useless feature of Java I know. For instance, when I google for static protected, here's what comes up on number 1:

Brad Abrams : New Design Guideline: Avoid Protected Static
Here is a minor update to the design guidelines around subclassing. It is based on this quiz I did a last week . Please let me know if you have any ...
blogs.msdn.com/brada/archive/2004/09/09/227332.aspx - 56k - Im Cache - �hnliche Seiten

There's no way we can simulate static protected without impairing the integrity of Scala's object model in a fundamental way. I refuse to let that happen. So, please keep the bug closed. We have been several times through this. I think it's unlikely I will change my position.

@scabug
Copy link
Author

scabug commented Mar 31, 2009

@paulp said:
Can they not just be treated as public? Feels like a big improvement over forcing people to write wrappers in java which expose all the members.

@scabug
Copy link
Author

scabug commented Mar 31, 2009

@milessabin said:
I don't dispute that protected static is poor practice and shouldn't be encouraged in Scala. But uses exist, in real and important Scala code, and limiting Scala's ability to interoperate with those is unfortunate.

I can see complications which would make it quite reasonable for you to toss it to the community and ask for patches. But I can think of at least one line of attack which wouldn't impair the integrity of Scala's object model in a fundamental way.

Can you point to somewhere that the compromise of Scala's object model has been explained?

@scabug
Copy link
Author

scabug commented Mar 31, 2009

@milessabin said:
Sorry, that should have been "real and important Java code" in the first para.

Also ... what Paul said: treating those Java statics as public would do the trick without in any way compromising the Scala object model or type system.

@scabug
Copy link
Author

scabug commented Apr 1, 2009

@jrudolph said:
It would be nice if drawbacks like this one would be mentioned somewhere centrally, so that one can find some explanation and a workaround. This ticket helps, but information should be added to [http://www.scala-lang.org/faq/4 Frequently Asked Questions - Java Interoperability] as well.

@scabug
Copy link
Author

scabug commented Jun 6, 2011

Commit Message Bot (anonymous) said:
(extempore in r25056) Carved out access exception for java protected statics, which
otherwise cannot be accessed from scala. Changes close status
of #1806, no review.

@scabug
Copy link
Author

scabug commented Aug 26, 2011

@paulp said:
Whoever reopened this, please attach your name and reasoning if you want it to stay reopened. Anonymous and unexplained database changes are not going to be allowed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants