Here is what I'm trying to accomplish
File 1: ./net/Class1.java
package net;
public class Class1
{
protected static class Nested
{
}
}
File 2: ./com/Class2.java
package com;
import net.Class1;
public class Class2 extends Class1
{
Nested nested = new Nested();
}
Here is the error I'm getting
>javac ./net/Class1.java ./com/Class2.java
.\com\Class2.java:7: error: Nested() has protected access in Nested
Nested nested = new Nested();
Is this error expected? Am I doing something wrong?
Problem
Few important facts (which many people forget or are not aware of):
default constructors (including ones for static and non-static nested classes) have same visibility as visibility of class which they belong to. So in case of protected class Nested{...} its default constructor is also protected.
element with protected visibility can be accessed only from class which
belongs to same package as class which declared that element,
extends (explicitly or implicitly) class which declared it.
Your Class2 extends Class1 so it only have access to members of Class1 (including access to Nested type). But since it
doesn't extend Nested (even implicitly, it only inherits access to it since it is protected)
doesn't belong to same package as Nested
it can't access protected elements from Nested class (including constructors).
Solution:
To solve that problem make Nested constructor public by either
explicitly creating no-argument constructor of Nested class with public modifier:
package net;
public class Class1 {
protected static class Nested {
public Nested(){
//^^^^^^
}
}
}
making Nested class public (its default constructor will also become public - see point 1.)
package net;
public class Class1 {
public static class Nested {
//^^^^^^
}
}
Related
In Java, if a nested class is not declared as static, it cannot be accessed within a static context. This means an instance of the inner class can only be created through an instance of the outer class. For example:
class Prac{
class Inner{}
public static void main(){
Inner myObj = new Prac().new Inner();
}
}
For my Java-adjusted brain, this makes sense. If an inner class isn't static, it would require an instance of the outer class to be instantiated from. In c# however, I can declare Inner non-statically as a nested class and directly instantiate it from a static context in the Main method.
I read that c# nested classes are like c++ and not java, but I'm not familiar with how inner classes work in any other way. What are the mechanics underlying nested classes in c#?
Consider that Microsoft strongly suggests to avoid public nested classes.
The core idea of a nested class is to completely hide to everyone an implementation detail of an abstraction. Consider that example:
IUserService
public interface IUserService
{
IEnumerable<string> GetAllUsernames();
}
MockUserServiceProvider
public static class MockUserServiceProvider
{
// Public
public static IUserService New() => new MockUserService();
// Nested Private class
private class MockUserService : IUserService
{
public IEnumerable<string> GetAllUsernames()
{
yield return "Bob";
yield return "Mary";
}
}
}
The goal of the Mock provider is to make available to the public an instance of the interface to Mock, it does not make sense to bind the provider to a specific class type, indeed, in theory, that type just shouldn't exist at all. So the best one can do (Without use some I.L. magic as Moq does for example) is to completely hide the class definition with a private nested class, so that no one can access it.
I was learning about Nested and Inner classes and this led me to think whether it is possible to extend an Inner class to be a Nested class or not. For example.
public class Outer{
public class Inner{
// notice the lack of static keyword
}
}
public class ExtendedOuter extends Outer{
public static class ExtendedInner extends Inner{
// notice the static keyword
}
}
I did try to compile the code above and I couldn't, but the compile time error I received made me believe that there may be a work around. I can however extend a Nested class to be an Inner class.
This is the compile time error I received.
no enclosing instance of type Outer is in scope
An inner class has a reference to the outer class. You cannot remove it in a subclass. This would be like removing a field in a sub-class.
Actually you can extend the inner class. You just have to provide an instance of Outer that the class will be bound to. To do so, you have to explicitly call the super constructor with the instance.
public class Outer {
public class Inner{
// notice the lack of static keyword
}
}
public class ExtendedOuter extends Outer {
private static Outer outer = new ExtendedOuter(); // or any other instance
public static class ExtendedInner extends Inner {
public ExtendedInner() {
outer.super(); // this call is explicitly required
}
}
}
This also works if you have a nested class that extends another nested class from a different enclosing class.
Your question doesn't make sense. An inner class is already a nested class, and so is any other class defined inside another one. Evidently you don't know what these words mean:
nested class: a class declared inside another one
inner class: a nested class that isn't declared 'static'.
Note that 'static nested' and 'inner' are mutually exclusive. Note also that an inner class can extend a static nested class, but not vice versa.
What your code is actually trying to do is extend the inner class as a static class, which is what causes the error. Not because the extending class is nested.
I was searching in google for something and I got a code like
public static abstract class LocationResult{
public abstract void gotLocation(Location location);
}
It's a nested class but wondering how it could be accessible ?
It must be a nested class: the static keyword on the class (not methods within it) is only used (and syntactically valid) for nested classes. Such static member classes (to use Java in a Nutshell's common nomenculture) hold no reference to the enclosing class, and thus can only access static fields and methods within it (unlike non-static ones; see any summary of nested classes in Java (also known as inner classes).
It can be accessible like this:
public class EnclosingClass {
public static abstract class LocationResult{
public abstract void gotLocation(Location location);
}
}
EnclosingClass.LocationResult locationResult = ...
Only nested classes can be static. By doing so you can use the nested class without having an instance of the outer class.
So you could create a class extending it using extends Mainclass.LocationResult and use it with Mainclass.LocationResult instance = ...
I have abstract java class which contains nested class declared as protected static:
public abstract class AbstractJavaClass {
// contains nested class
protected static class InnerClass {
...
}
}
When I'm trying to instantiate it in Scala class extending AbstractJavaClass like I do in java (i.e. just referring name inside method new InnerClass):
class ScalaClass extends AbstractJavaClass {
def method = new InnerClass()
}
I get error: type InnerClass is not a member of ScalaClass. What am I doing wrong? The same in java works fine.
Stumbled here: access java base class's static member in scala
It says
This isn't possible in Scala. Since Scala has no notation of static you can't
access protected static members of a parent class. This is a known limitation.
Though I couldn't resolve initial issue (when class is protected static), when I changed it to public static in definition of AbstractJavaClass I could use it this way:
class ScalaClass extends AbstractJavaClass {
import AbstractJavaClass.InnerClass
def method = new InnerClass
}
Using new InnerClass without import gives the same error.
If I write an abstract class, then nest a class in the abstract class, will I have access to its methods in any subclasses of the abstract class? I cannot find the answer anywhere..
Of course, access modifiers on inner classes obey the same rules as on fields and methods. It does not matter whether your class is abstract or concrete, as long as the nested class is either public, protected or the subclass is in the same package and the inner class is package private (default access modifier), the subclass will have access to it.
public abstract class AbstractTest {
// all subclasses have access to these classes
public class PublicInner {}
protected class ProtectedInner {}
// subclasses in the same package have access to this class
class PackagePrivateInner {}
// subclasses do not have access to this class
private class PrivateClass {}
}
class Abstract {
modifier1 class Nested { modifier2 int i = 0; }
Abstract() {
Nested n = new Nested();
n.i = 1;
}
}
class Sub extends Abstract {
Sub() {
Nested n = new Nested();
// have access as long you not choose "private"
// for `modifier1` or `modifier2`:
n.i = 5;
}
}
If the nested class is at least protected, we can access its methods (as long as the methods are public or we are in the same package and they are not private).
But you could have tried this out yourself easily :-)