Examples of the use of inner classes in conjunction with interfaces. Downward and upward conversion. The advantages of using upward conversion
Contents
- 1. The essence of the downward conversion
- 2. Features of the implementation of the upward conversion in the case of an internal private class
- 3. The advantages of using upstream conversion in conjunction with inner classes
- 4. Features of the implementation of the upward conversion in the case of the internal protected-class
- 5. An example that demonstrates a downward conversion
- 6. An example that demonstrates an upward conversion
- 7. What is the difference between the downward conversion and the upward conversion? Example
- Related topics
Search other websites:
1. The essence of the downward conversion
If the inner class InClass, which has public access, is declared in OutClass
class OutClass { public class InClass { // implementation of the class InClass // ... // implementation of methods of class InClass int method1() { // instructions // ... } int method2() { // instructions // ... } } }
then in the case of a downward conversion, use the methods method1(), method2() of the class InClass according to the following scheme
// demonstration of the use of downward conversion // create an object of class OutClass in the standard way OutClass oc = new OutClass(); // create an object of class OutClass.InClass using the instruction .new OutClass.InClass ic = oc.new OutClass.InClass();
So, in a downward conversion, it is important that the inner class has public access.
⇑
2. Features of the implementation of the upward conversion in the case of an internal private class
If you need to take advantage of the upstream conversion for the inner class, then you need to follow the steps below. For example, the internal class is considered, which should provide the client programmer with two methods for using with limited access to other types and implementations of the internal class. Methods are named method1(), method2().
The sequence of steps is as follows.
1. Declare the private-inner class InClass in the outer class OutClass
class OutClass { private class InClass { // implementation of the class InClass // ... // implementation of methods that should be available to the client programmer int method1() { // instructons // ... } int method2() { // instructions // ... } } }
After such a declaration, access to the internal private class InClass has only the external class OutClass. The client programmer does not have access to the InClass class. It is also impossible to perform a downward conversion to the private class InClass by calling
OutClass oc = new OutClass(); // OutClass.InClass ic = oc.new InClass(); - error!
2. Declare interface. At this step, you need to declare the interface and select internal methods that will be available to the client programmer and also modify the declaration of the InClass class. These methods are implemented in the class InClass according to the following sample
public interface InterfaceInClass { // interface methods that are presented for use by the client programmer int method1(); int method2(); } class OutClass { // data and methods of class OutClass // ... // implementation of the class InClass with the InterfaceInClass interface methods private class InClass implements InterfaceInClass { // ... // implementation of interface methods int method1() { // ... } int method2() { // ... } } }
In the above code, two methods are provided to the client programmer.
int method1(); int mehtod2();
The names of the methods and their parameters are chosen at random.
3. Declare a method that implements an upstream conversion. At the third stage, a method is formed in the OutClass class that returns an object of the InClass class. After these changes, the interface declaration InterfaceInClass and class OutClass will look like this:
public interface InterfaceInClass { // interface methods that are provided for use by the client programmer int method1(); int method2(); } class OutClass { // data and methods of class OutClass // ... // implementation of the class InClass based on interface methods private class InClass implements InterfaceInClass { // ... // implementation of interface methods int method1() { // instructions // ... } int method2() { // instructions // ... } } // OutClass class method that returns an InterfaceInClass interface object public InterfaceInClass GetInterfaceInClass() { // some instructions (may be absent) // ... return new InClass(); // return the instance of class InClass } }
The above implementation of the inner class InClass in the outer class OutClass defines the essence of the upstream conversion. The object of the inner class is obtained on a bottom-up basis.
For the above example, the client programmer can use the inner class as follows:
// get an object of class OutClass OutClass oc = new OutClass(); // using the method GetInterfaceInClass get the object ic InterfaceInClass ic = oc.GetInterfaceInClass(); // invoke the method through the received object ic int res; res = ic.method1();
⇑
3. The advantages of using upstream conversion in conjunction with inner classes
The implementation of the upstream conversion gives the developer the following advantages:
- direct access to internal classes is prohibited;
- hiding all the details of the implementation of the inner class;
- the client-programmer is given access only to the necessary (limited) implementations of the inner class;
- it will not make sense for the client programmer to extend the interface by adding new methods, since it will not have access to additional methods that do not belong to the open part of the class;
- the Java compiler will be able to optimize the code.
⇑
4. Features of the implementation of the upward conversion in the case of the internal protected-class
The upward conversion for internal protected classes works according to the same principle as for internal private classes as described in Section 2. In the case of private classes, the outer class has access to the inner class. In the case of protected-classes, access to the inner class have:
- external class;
- the class inherited from an external class;
- classes of its own package, in which the outer class is declared. The protected specifier gives access within its own package.
For protected-classes, you can make a downward conversion only from the inherited class.
⇑
5. An example that demonstrates a downward conversion
The external class Calculation is declared, which implements many internal classes that perform mathematical calculations on numbers. One of the inner classes is called Complex. It implements basic operations on complex numbers. As a result of the declaration, the Calculation class has the form:
// external class that contains the implementation of the Complex class class Calculation { // the inner class Complex public class Complex { double real; // real part double imag; // imaginary part // method that returns the modulus of a complex number double Abs() { return Math.sqrt(real*real+imag*imag); } } }
Using the Complex class in another method demonstrates a downward conversion.
// downward conversion // create an object of the class Complex using the object of the Calculation class Calculation calc = new Calculation(); Calculation.Complex comp = calc.new Complex(); double res; comp.imag = 3; comp.real = 5; // invoke the method of calculating the modulus of a complex number res = comp.Abs(); // res = 5.830951894845301
⇑
6. An example that demonstrates an upward conversion
Given the Calculation class, which implements the hidden (private) inner class Complex. The Complex class declares its public Abs() method using the IComplex interface. The implementation of the Calculation class and the IntComplex interface is as follows:
// interface containing the Abs() method signature interface IntComplex { double Abs(); } // outer class that contains the inner hidden class Complex class Calculation { // class implements IntComplex interface, handles complex numbers private class Complex implements IntComplex { // internal data of class Complex private double imag; // imaginary part of a complex number private double real; // real part // class constructor with two parameters public Complex(double _imag, double _real) { imag = _imag; real = _real; } // implementation of the method that is declared in the IntComplex interface public double Abs() { return Math.sqrt(real*real+imag*imag); } } // return the object of class Complex public IntComplex GetComplex(double _imag, double _real) { // return the object of inner class return new Complex(_imag, _real); // call the constructor with 2 parameters } }
The GetComplex() method of the Calculation class returns an object (instance) of the inner class Complex, thereby implementing an upward conversion. When creating an object of the Complex class in the GetComplex() method, a constructor with 2 parameters is called. The following demonstrates the use of the Complex class in another method.
// upward conversion Calculation calc = new Calculation(); // create an object of the outer class IntComplex ic = calc.GetComplex(5, 6); // get the object of inner class double res; // call inner class method res = ic.Abs(); // res = 7.810249675906654
Using the IntComplex() interface, the client programmer has access to the methods of the internal hidden class Complex. Access is via the external object of class Calculation.
⇑
7. What is the difference between the downward conversion and the upward conversion? Example
The difference between ascending and descending conversion is manifested in the method of obtaining an object of the inner class. In a downward conversion, an inner class object is created using the .new operator by referring to the name of the outer class object
// downward conversion OutClass oc = new OutClass(); // create an object of the outer class OutClass.InClass ic = oc.new InClass(); // create the object of inner class
For an upward conversion, an inner class object is obtained using a special method of the outer class, as shown below
OutClass oc = new OutClass();
OutClass.InClass ic = oc.GetObjInClass();
here GetObjInClass() – method that creates an instance of the inner class OutClass.InClass. In this case, the inner class OutClass.InClass must have public or protected access for the inherited class. In the case of the implementation of the inner class in combination with the interface, the software code of the upward transformation may look as follows:
OutClass oc = new OutClass();
InterfaceInClass ic = oc.GetInterfaceInClass();
here
- OutClass – external class for which an object is created with the name oc;
- InterfaceInClass – an interface that declares inner-class methods for use by a client programmer;
- GetInterfaceInClass() – a method that returns an object (a specific instance) of the inner class OutClass.InClass(), which implements the InterfaceInClass interface.
⇑
Related topics
- 1. Nested classes and inner classes. Static nested classes. Example
- 2. Creating the objects of nested static and non-static classes. Constructions .this, .new