I'm reading a book "Thinking in Java" that states the following about inner classes:
Each inner class can independently inherit from an implementation. So one way to look at the inner class is as the rest of the solution of the multiple-inheritance problem. Interfaces solve part of the problem, but inner classes effectively allow "multiple implementation inheritance". That is, inner classes effectively allow you to inherit from more than one non-interface.
I've never used inner classes like that. So I started to thinking about how this could look and where this can be useful. I came up with this:
public class ReadWriteCollection {
public static void main(String[] args) {
var rw = new ReadWriteCollection();
var ro = rw.new ReadPart();
var ao = rw.new AddPart();
ao.add("foo");
System.out.println(ro.read(0));
}
private List<String> list = new ArrayList<>();
class AddPart extends AddOnlyCollection {
void add(String s) { list.add(s); }
}
class ReadPart extends ReadOnlyCollection {
String read(int index) { return list.get(index); }
}
public abstract static class ReadOnlyCollection {
final void someExistingImplementation(){ System.out.println("Foo"); }
abstract String read(int index);
}
public abstract static class AddOnlyCollection {
final void someExistingImplementation(){ System.out.println("Bar"); }
abstract void add(String s);
}
}
ReadOnlyCollection and AddOnlyCollection represent some existing implementations that I can't control. I've put them inside ReadWriteCollection just for convenience in my example.
So is it how inner classes should be used for "multiple implementation inheritance"? Can somebody give more examples and possible usages for this technique? Or is it the way inner classes were used in the past and no longer used like this (the book is quite old)?
I guess the idea of the author is the following to by-pass the multi inheritance restriction in Java:
public class A {}
public class B {}
public class C {}
public class MainTest {
private AA aa;
private BB bb;
private CC cc;
public static void main(String[] args) {
AA aa = new AA();
BB bb = new BB();
CC cc = new CC();
}
private static class AA extends A {
}
private static class BB extends B {
}
private static class CC extends C {
}
}
With that you have extended three different classes inside your MainTest.
Related
I'm trying to create some system with inner class. My code can be summarized to something like this.
public abstract class A {
public abstract void doSomething();
}
public class B {
public final ArrayList<A> list=new ArrayList<A>();
public B(){
}
}
public class C {
private int i;
public C(B b){
b.list.add(new A(){
public void doSomething(){
i++;
}
});
b.list.add(new A(){
public void doSomething(){
System.out.println(i);
}
});
}
}
public static void main (String[] arg) {
B manager=new B();
new C(manager);
new C(manager);
new C(manager);
}
A is abstract class that will be inherited as inner class (in my original code it is listener class), B is some kind of manager class that hold list of As, and C hold data it's data should be only modified or read by it's inner class and upon initialization it add A to the class B. Code itself works fine. But problem is as there will be various kinds of C something like C2, C3 that does different thing and this leads to my code overwhelmed with thousands of unassigned object new C(manager); this make debugging extra hard and code looks really ugly. So it seems to me my approach in the first place was wrong but have no idea how to avoid this. So how should I change my approach to not have thousands of unassigned objects?
My suggestion is: try not to use constructors to do operations that depend on state (i). Use static functions, and save the state in a separate class (we call it a “context”).
import java.util.ArrayList;
public class Demo {
// A
abstract static class InnerListener {
public abstract void onEvent();
}
// B
static class ListenerManager {
public final ArrayList<InnerListener> listeners = new ArrayList<InnerListener>();
}
static class SideEffectContext {
public int i = 0;
}
// C
static class ListenerUtil {
public static void setupListeners(ListenerManager manager, SideEffectContext context) {
manager.listeners.add(new InnerListener() {
public void onEvent() {
context.i++;
}
});
manager.listeners.add(new InnerListener() {
public void onEvent() {
System.out.println(context.i);
}
});
}
}
public static void main(String[] arg) {
var manager = new ListenerManager();
var ctxA = new SideEffectContext();
var ctxShared = new SideEffectContext();
ListenerUtil.setupListeners(manager, ctxA);
ListenerUtil.setupListeners(manager, ctxShared);
ListenerUtil.setupListeners(manager, ctxShared);
}
}
I'm trying to convert following c# code and behavior to Java but I'm struggling to find the right syntax or programming pattern.
In c# I can use out like in interface IProxy<out Target> which allows me to implicitly cast IProxy<DerivedElement1> to IProxy<BaseElement> but for Java I'm not aware of any similar generic modifiers.
class BaseElement {
public static readonly Property<BaseElement> P1 = new Property<BaseElement>();
}
class DerivedElement1 : BaseElement {
public static readonly Property<DerivedElement1> P2 = new Property<DerivedElement1>();
}
class DerivedElement2 : BaseElement {
public static readonly Property<DerivedElement2> P2 = new Property<DerivedElement2>();
}
class Property<Owner> {
}
interface IProxy<out Target> {
}
class Proxy<Target> : IProxy<Target> {
}
class Program {
static void doSomething<Target>(IProxy<Target> proxy, Property<Target> property) {
// ...
}
static void Main(string[] args) {
Proxy<DerivedElement1> proxy1 = new Proxy<DerivedElement1>();
doSomething(proxy1, DerivedElement1.P1);
doSomething(proxy1, DerivedElement1.P2);
// expected error
doSomething(proxy1, DerivedElement2.P2);
}
}
It is very important that the expected error appears at compile time and not at run time.
Are you aware of any applicable syntax or pattern that would allow me to implement the same behavior without any additional casting?
I hope you can point me in the right direction, thank you much for your help!
I found out that I can use Proxy<? extends Target> to declare my proxy argument.
Here is the complete solution:
class BaseElement {
public static final Property<BaseElement> P1 = new Property<BaseElement>();
}
class DerivedElement1 extends BaseElement {
public static final Property<DerivedElement1> P2 = new Property<DerivedElement1>();
}
class DerivedElement2 extends BaseElement {
public static final Property<DerivedElement2> P2 = new Property<DerivedElement2>();
}
class Property<Owner> {
}
class Proxy<Target> {
}
class App {
static <Target>
void doSomething(Proxy<? extends Target> proxy, Property<Target> property) {
// ...
}
static void main(String[] args) {
Proxy<DerivedElement1> proxy1 = new Proxy<DerivedElement1>();
doSomething(proxy1, DerivedElement1.P1);
doSomething(proxy1, DerivedElement1.P2);
// expected error
doSomething(proxy1, DerivedElement2.P2);
}
}
If Ive got you correctly you should have a look at generic type in Java.
Sample Java Code
public class IProxy<T>{
....
}
public class Property<T>{
....
}
public class Program {
public static void doSomething(<IProxy<T> iProxy, Property<T> property){
......
}
}
Type Parameter Naming Conventions (not sure what Target is referring to in C#)
E - Element (used extensively by the Java Collections Framework)
K - Key
N - Number
T - Type
V - Value
S,U,V etc. - 2nd, 3rd, 4th types
when you extend a private class. Are the public and protected members of class become private. if not any explanation.
if you extend a nested private class, it wont change public/protected modifiers of the members. Here is an example :
public class Clazz {
private static class NestedClazz {
public int value = 123;
}
public static class NestedClazzExt extends NestedClazz {
}
}
you can now access the inherited member: value from outside
public static void main(String[] args) {
NestedClazzExt nestedClazz = new Clazz.NestedClazzExt();
System.out.println(nestedClazz.value);
}
you can create private class in side a class . We call it as Nested classe. Means a class inside a class. The Concept itself is saying that you can create private class in side another class. The private class will act like as data member to the outer class.
So, You can't extend the private class.
Based on your query I tried to prepare a simple class.
public class pvtClass {
private class As {
public String abc = "private attribute";
public void print(){
System.out.println("privateClass");
}
}
class Ab extends As{
public String ab = "extended attribute";
public void printAb(){
System.out.println("extended class");
print();
System.out.println(abc);
}
}
public static void main(String as[]){
Ab ab1 = (new pvtClass()).new Ab();
As as1 = (new pvtClass()).new As();
ab1.printAb();
as1.print();
System.out.println(as1.abc);
}
}
If you have a look at this class, I have a private class named "As" which has public attribute and public methods. I have another class named "Ab" which extends "As". I have written a main method to invoke the private attribute and methods.
below is the output for the code snippet:
extended class
privateClass
private attribute
privateClass
private attribute
There is a difference between the access of the members of a class and the access to the type itself.
public class C {
private class InnerP1 {
public void m() {
System.out.println("InnerP1.m()");
}
}
private class InnerP2 extends InnerP1 {
public void p() {
this.m();
System.out.println("InnerP2.p()");
}
}
public InnerP1 strange() {
return new InnerP2();
}
}
In this example, the interface I is visible from outside class C. The classes InnerP1 and InnerP2 are not visible from outside C. Jave itself makes not restrictions to the visibility of types you use in your public interface. The method strange() of class C returns a result of class InnerP1. Since outside of C we do not know anything about the class InnerP1 other than it is subtype of Object, the only thing we can do is use the result of strange() as an Object.
public class D {
public static void main(String[] args) {
C c = new C();
Object o = c.strange();
if(o.equals(c.strange())) {
System.out.println("Strange things are going on here!");
}
}
}
As #KnusperPudding pointed out already, the visiblity of public members is not changed, we might just not have enough knowledge of the type itself to access them.
Access to members cannot be restricted by sub-classing. When you mark a class as private then access via the class name is restricted i.e. to the same .java file, however once you have an instance of this class it can be accessed at least as easily as the super class.
I was trying to develop an interface and that interface will contain static class
class C1 {
static interface I // A static interface or class can contain static members.Static members can be
//accessed without instantiating the particular class
{
static class C2 {
}
}
public static void main(String a[]) {
C1.I.C2 ob1 = new C1.I.C2();
System.out.println("object created");
}
}
But my query is that can interface contain classes which are not static and if yes , then how their object would be created , please advise. Thanks
Can an interface contain classes?
Yes. For example, in
interface Widget {
static class Factory {
static Widget create() { return new Widget() {}; }
}
}
the inner class can be accessed as
Widget w = Widget.Factory.create();
so to refer to the inner class you can just use the interface name then a dot then the inner class name
import my.pkg.MyInterface;
...
MyInterface.InnerClass ic = new MyInterface.InnerClass();
I have two parallel class hierarchies and I would like to convert objects from one to another. I can do it by manually specifying what conversion to do, but I need to specify the conversion twice: first when the actual conversion happens and second when I need to call it. Is there a way to specify it only once?
So here is the example, that works, but I would like to simplify. There are two convert functions that allow me to go between input classes (bI, cI) and output classes (bO, cO). This is unavoidable. The instanceof comparisons though bother me. Is there an elegant solution to avoid them?
public class ConversionTest {
static public class aI {}
static public class bI extends aI {}
static public class cI extends aI {}
static public class aO {}
static public class bO extends aO {}
static public class cO extends aO {}
// Convert from bI to bO.
private static aO convert(bI iVar) {return new bO();}
// Convert from cI to cO.
private static aO convert(cI iVar) {return new cO();}
public static void main(String argv []) {
// Input variable.
final aI iVar = new bI();
// Output variable.
final aO temp;
// Perform conversion.
if(iVar instanceof bI) {
temp = convert((bI)iVar);
} else if (iVar instanceof cI) {
temp = convert((cI)iVar);
}
}
}
I would like to do something like that:
final a0 temp = convert(iVar.getClass().cast(iVar));
But in this case, compiler complains that it can not find the proper convert function. Maybe I can specify an array of all possible conversions to try?
final a0 temp = convertHelp({bI,cI}, iVar);
I am not sure how I should implement this convertHelp function. It would iterate through the array and try to find the proper casting. Any suggestions?
Thanks.
Do you have access to the class implementations themselves? You could use polymorphism to make the conversion do the right thing if you stick it inside each class.
class ai
{
public ao convert()
{
return new ao();
}
}
class bi extends ai
{
#Override
public ao convert()
{
return new bo();
}
}
class ci extends ai
{
#Override
public ao convert()
{
return new co();
}
}
public static void main(String argv []) {
// Input variable.
final aI iVar = new bI();
// Output variable.
final aO temp = iVar.convert();
}
Given that you can't modify the input/output classes, the cleanest solution may be to use reflection:
class Converter {
public ao convert(ai iObj) {
final Method m = getClass().getDeclaredMethod("cvrt", iObj.getClass());
return (ao)m.invoke(this, iObj);
}
public ao cvrt(ai iObj) {
return new ao();
}
public bo cvrt(bi iObj) {
return new bo();
}
public co cvrt(ci iObj) {
return new co();
}
}
The implementation you already have is correct, and it's much prettier than what you'd get using the reflection APIs.
You can implement ConvertHelp; it would need to take an array of Class objects as parameter. But, again, the body of ConvertHelp would be very ugly.
What you are doing is against the ideals of a statically typed language. Java is not designed to make it easy - it's very easy to produce unsafe code this way.
private static aO convert(aI iVar) {
if (iVar instanceof bI)
return new bO();
if (iVar instanceof cI)
return new cO();
return new aO();
}
If you don't want your input classes to be dependent on the output classes, you can still benefit from polymorphism:
interface IFactory<T> {
public T createA();
public T createB();
public T createC();
}
class ai
{
public T convert(IFactory<T> f)
{
return f.createA();
}
}
class bi extends ai
{
#Override
public T convert(IFactory<T> f)
{
return f.createB();
}
}
class ci extends ai
{
#Override
public T convert(IFactory<T> f)
{
return f.createB();
}
}
class FactoryO extends IFactory<ao> {
public ao createA() {
return new ao();
}
public bo createB() {
return new bo();
}
public co createC() {
return new co();
}
}
To perform the conversion:
FactoryO f = new FactoryO();
ai ivar = // ...
ao ovar = ivar.convert(f);
Ideally, as suggested by the other posters, you should have a convert method on the input classes so that they can yield the output classes by themselves. If you want to have a parallel hierarchy of converters, your best recourse is to use the Visitor pattern.
You can define a ConverterVisitor interface and have two implementations as follows:
static public interface ConverterVisitor {
public aO convert(aI iVar);
}
static public class bIConverter implements ConverterVisitor{
public aO convert(aI iVar){
// requires a cast from aI to bI
return new bO();
}
}
static public class cIConverter implements ConverterVisitor{
public aO convert(aI iVar){
// requires a cast from aI to cI
return new cO();
}
}
But the bI and cI classes need to be modifiable as well which is not what you want to do.
Hence the only solution that remains is to use a ReflectionVisitor pattern.
This would involve writing a class that would fetch the corresponding converter using some kind of naming convention. In this case the converter's name is obtained using the convention of appending "Converter" to the class name. So a converter factory implementation may look like this:
static public class ConverterFactory {
public aO convert(aI ai) throws Exception {
return (aO) ((ConverterVisitor) Class.forName(ai.getClass().getName() + "Converter").newInstance()).convert(ai);
}
}
Very ugly! but it works!
The second alternative is to use some kind of registry in your factory.
Here is full listing. This is better since it uses generics to avoid multiple casts.
import java.util.HashMap;
import java.util.Map;
public class Trial {
static public class aI {}
static public class bI extends aI {}
static public class cI extends aI {}
static public class aO {}
static public class bO extends aO {}
static public class cO extends aO {}
static public interface ConverterVisitor<T extends aI> {
public aO convert(T iVar);
}
static public class bIConverter implements ConverterVisitor<bI>{
public bIConverter(ConverterFactory converterFactory){
converterFactory.register(bI.class, this);
}
public aO convert(bI iVar){
return new bO();
}
}
static public class cIConverter implements ConverterVisitor<cI>{
public cIConverter(ConverterFactory converterFactory){
converterFactory.register(cI.class, this);
}
public aO convert(cI iVar){
return new cO();
}
}
static public class ConverterFactory {
public Map<Class<?>,ConverterVisitor<?>>converterRegistry = new HashMap<Class<?>, ConverterVisitor<?>>();
public <T extends aI> void register(Class<T> clazz,ConverterVisitor<T> converter){
converterRegistry.put(clazz,converter);
}
#SuppressWarnings("unchecked")
public<T extends aI> aO convert(T ai) {
return ((ConverterVisitor<T>)converterRegistry.get(ai.getClass())).convert(ai);
}
}
public static void main(String argv []) throws Exception {
// Input variable.
final aI iVar = new bI();
// Output variable.
aO temp = null;
// the three lines below must be done in some generic place within the program.
ConverterFactory factory = new ConverterFactory();
new bIConverter(factory);
new cIConverter(factory);
temp = factory.convert(iVar);
System.out.println(temp);
}
}