How a nested default interface differs from a nested protected interface? - java

What are the differences between nested default and nested protected interfaces in Java? Why nested protected interfaces are even allowed?
Test.java
public class Test {
// not implementable outside of current package
interface NestedDefaultInterface {
}
// not implementable outside of current package?
protected interface NestedProtectedIface {
}
}
// both interfaces can be implemented
class Best implements Test.NestedProtectedIface, Test.NestedDefaultInterface {
}
MyClass.java
class AClass implements Test.NestedProtectedIface { //Error
}
class AnotherClass implements Test.NestedDefaultInterface { //Error
}
class OneMoreClass extends Test implements Test.NestedProtectedIface { //Error
}

To show the visual difference:
package com.one
public class Test {
// not implementable outside of current package
interface NestedDefaultInterface {
}
// implementable in child classes outside of package
protected interface NestedProtectedIface {
}
}
Outside of the package:
package com.two
class SubTest extends Test {
public void testProtected() {
NestedProtectedIface npi = new NestedProtectedIface () {
// implementation
};
}
public void testDefault() {
// Won't compile!
// NestedDefaultInterface ndi = new NestedDefaultInterface() {
// };
}
}
The confusion here is about visibility.
When you extending a class you will get access to all protected parent properties from this reference.
For default access modifier it will not work outside of the package.
The most popular real-world example of nested interface is Map.Entry<K,V> of java.util.Map.
Each implementation of Map provides its own Entry<K,V> implementation. (Node<K,V> in HashMap, Entry<K,V> in TreeMap and etc.)

Related

In Java, is it OK to require classes that implement an interface to inherit from a specific base class?

Quick style question:
I have a Java interface that defines functions that must be implemented by classes in a particular hierarchy, all descended from a specific base class.
There are contexts where I will be dealing with these classes through a pointer to the interface, but I need a pointer to the base class instead.
Example:
public class Base {}
public interface ChildRequirements {
Base asBase();
}
public class Child extends Base implements ChildRequirements {
Base asBase() { return this; }
}
public class SomeClass {
public void doSomething(Base base) { }
public void doSomethingElse(ChildRequirements creqt) {
doSomething(creqt.asBase());
}
}
Is this bad form? Am I thinking about this the wrong way? Should I just cast creqt as Base and ignore the warnings?
I have a Java interface that defines functions that must be implemented by classes in a particular hierarchy, all descended from a specific base class.
Then it isn't an interface, it's an abstract base class. Get rid of ChildRequirements and instead have Base define the requirements and mark it abstract:
abstract public class Base {
// ...required methods here, `abstract` if you don't have a
// base implementation...
}
public class Child extends Base {
// ...implements any `abstract` methods...
}
public class SomeClass {
public void doSomething(Base base) { }
public void doSomethingElse(Base creqt) {
doSomething(creqt);
}
}
But whenever possible, program to interfaces, not abstract classes.
I don't see the difference between your typing and just using interfaces and ol'regular inheritance. Your return this in the Child class seems to suggest you expect it to be a subtype of Base. The way the interfaces are structured it seems like you are actually expressing an is-a relationship between Base and ChildRequirements, but decorating the super class.
Alternate typing:
//Straight-forware inheritance
public interface Base {
}
interface ChildRequirements extends Base{
Base asBase();//return the super
}
class Child implements ChildRequirements {
public Base asBase() { return this;}
}
class SomeClass {
public void doSomething(Base base) { }
public void doSomethingElse(ChildRequirements creqt) {
doSomething(creqt.asBase());
}
}

Overwriting the List type of the parent class to avoid casting when calling methods

I have an input file (text => TextFileImporter or xml => XmlFileImporter) which contains data with different structures. A structure is described in the Definiton class, so my FileImporter object holds multiple instances of Definition.
A TextFileImporter should hold List<TextDefinition> and a XmlFileImporter should hold List<XmlDefinition>.
Please have a look at the example code:
// Parent classes
abstract class Definition {}
abstract class FileImporter {
protected List<Definition> definitions;
public FileImporter(List<Definition> definitions) {
this.definitions = definitions;
}
public void doSomething() {
// use 'definitions'
}
}
// Text files
class TextDefinition extends Definition {
public void copyLine() {}
}
class TextFileImporter extends FileImporter {
// here should be clear that 'definitions' is of type List<TextDefinition>
// to call 'copyLine()' on its items
}
// XML files
class XmlDefinition extends Definition {
public void copyNode() {}
}
class XmlFileImporter extends FileImporter {
// here should be clear that 'definitions' is of type List<XmlDefinition>
// to call 'copyNode()' on its items
}
As you can see on the basis of the comments I'm not sure how to handle that preferably. Of course I first need constructors. Then, I don't want to cast each item of definitions to the suitable subclass every time just to call a method.
Can I make a reasonable use of generics here? Or is there another solution?
You have to introduce some generics.
// Parent classes
abstract class Definition {}
abstract class FileImporter<T extends Definition> {
protected List<T> definitions;
public FileImporter(List<T> definitions) {
this.definitions = definitions;
}
public void doSomething() {
// use 'definitions'
}
}
// Text files
class TextDefinition extends Definition {
public void copyLine() {}
}
class TextFileImporter extends FileImporter<TextDefinition> {
// here should be clear that 'definitions' is of type List<TextDefinition>
// to call 'copyLine()' on its items
}
// XML files
class XmlDefinition extends Definition {
public void copyNode() {}
}
class XmlFileImporter extends FileImporter<XmlDefinition> {
// here should be clear that 'definitions' is of type List<XmlDefinition>
// to call 'copyNode()' on its items
}

Instantiate an inner class inherited with protected access specifier

I wanted to make the following exercise from Bruce Eckel's TIJ on inner classes:
Create an interface with at least one method, in its own package.
Create a class in a separate package. Add a protected inner class
that implements the interface. In a third package, inherit from
your class and, inside a method, return an object of the protected
inner class, upcasting to the interface during the return.
Here's my implementation:
first, the interface:
package workers;
public interface Employable {
void work();
}
then, a class with an inner class implementing the interface:
package second;
import workers.Employable;
public class WorkersClass {
protected class Worker implements Employable {
#Override
public void work() {
System.out.println("Hello, I'm a worker!");
}
}
}
and finally the inherited class:
package third;
import second.WorkersClass;
import workers.Employable;
public class Third extends WorkersClass {
Employable getWorker() {
return new Worker();//the line is reported to be incorrect
}
}
IDEA underlines the line with Worker() in getWorker and suggests to make the Worker class public. But why? It's protected that's why successors of WorkersClass can instantiate the Worker class in their methods. Do I misunderstand something?
The problem is not all with access specifier.
When you don't provide any constructor in a class, the compiler automatically inserts a default, no-args constructor for you
That's not true here in this case. Because the compiled inner class doesn't get the default constructor since it gets compiled as outer$inner and for that inner there is no default constructor provided by compiler.
Provide a default no org constructor manually and see the magic :)
package second;
import workers.Employable;
public class WorkersClass {
protected class Worker implements Employable {
public Worker() {
// TODO Auto-generated constructor stub
}
#Override
public void work() {
System.out.println("Hello, I'm a worker!");
}
}
}
modify WorkersClass
public class WorkersClass {
protected class Worker implements Employable {
public Worker(){}
#Override
public void work() {
System.out.println("Hello, I'm a worker!");
}
}
}
Your Third class inherits WorkersClass and not Worker.
Java does not really consider inner classes, it is a simple hack introduced in Java 1.1. The compiler generates class Worker "outside" of class WorkersClass, but in the same package.
That's why, in order to implement a new Worker instance from a Third method, you need to add a public constructor to Worker:
protected class Worker implements Employable {
public Worker(){
}
#Override
public void work() {
System.out.println("Hello, I'm a worker!");
}
}

scope of private constructor in Nested Class

This is more of a puzzle than question. I have the following code:
public class PrivateBaseConstructor {
public static class BaseClass {
private BaseClass() {
}
}
public static class DerivedClass extends BaseClass {
public DerivedClass() {
super(); // 1*
}
}
}
Here the call for super(); at 1* is allowed even though the base class constructor is private. If we write the classes as separate classes in same package:
BClass.java
public class BClass {
private BClass() {
}
}
DClass.java
public class DClass extends BClass {
public DClass() {
super(); // 2*
}
The compiler rightly gives an error at 2* since the base class constructor is not visible.
Why doesn't the compiler throw an error in my first scenario when both the classes are declared static within one class?
if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (ยง7.6) that encloses the declaration of the member or constructor.
http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6.1
Because nested classes can see each others members. This has nothing to do with the static declarations. See the following example of your code with just nested inner classes (not static).
public class PrivateBaseConstructor {
public class BaseClass {
private BaseClass() {}
}
public class DerivedClass extends BaseClass {
public DerivedClass() {
super(); // 1*
}
}
public static void main(String[] args)
{
new PrivateBaseConstructor(). new DerivedClass();
}
}
Read more about nested classes here: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
Because anything declared inside a class can access its private members, including inner classes. However, if you run PMD on your class, you'll find it suggests you change the visibility of the constructor to not-private.

Extending nested class from abstract class in a subclass and making the methods use the new definition of the nested class

I have a base abstract class with a nested class inside of it. In one of the subclasses I need to extend the nested class, but the abstract methods inherited from the base class expect the base class definition of the nested class (for return types and arguments). How can I make them use the new definition of the nested class?
Also the nonabstract methods(which I'm not overriding) don't work properly either(and they worked fine before I moved them to the abstract class).
abstract class Base {
protected class Nested{
....
}
protected abstract Nested someMethod();
protected void anotherMethod(Nested x){
......
}
}
class Derived {
class Nested extends Base.Nested {
....
}
protected Nested someMethod() {
......
}
}
I think the best route would be to declare a protected, optionally abstract factory method to create the Nested class.
Something like this:
abstract class Base {
protected class BaseNested {
....
}
protected abstract BaseNested newNested();
}
class Derived extends Base {
class DerivedNested extends BaseNested {
....
}
protected BaseNested newNested() {
return new DerivedNested();
}
}
Then when your base class wants a new BaseNested, it calls newNested instead of new DerivedNested().
If for some reason you need Derived to only deal with Derived.Nested for those methods, and not Base.Nested (you should carefully evaluate that decision) then you can use generics. Type Base on the type of nested class it deals with:
abstract class Base<T extends BaseNested> {
protected abstract T newNested();
protected abstract T someMethod();
protected void anotherMethod(T nested) {
//...
}
}
class Derived extends Base<DerivedNested> {
protected DerivedNested newNested() {
return new DerivedNested();
}
//...
}

Categories