12 Replies - 451 Views - Last Post: 12 September 2011 - 02:36 PM Rate Topic: -----

#1 Zel2008  Icon User is offline

  • D.I.C Addict

Reputation: 14
  • View blog
  • Posts: 790
  • Joined: 06-January 09

Inner classes and enclosing instances

Posted 12 September 2011 - 09:27 AM

Please look at the next post down (#2), this first post (#1) was a mistake.

This post has been edited by Zel2008: 12 September 2011 - 09:35 AM

Is This A Good Question/Topic? 0
  • +

Replies To: Inner classes and enclosing instances

#2 Zel2008  Icon User is offline

  • D.I.C Addict

Reputation: 14
  • View blog
  • Posts: 790
  • Joined: 06-January 09

Re: Inner classes and enclosing instances

Posted 12 September 2011 - 09:30 AM

Hi everybody,
I have a class in a file with a few tiny classes that only it uses, set up like this, all in the same file:

public class A {
    public static void main( String args[] ) {
        new C();
        new D();
    }
}
private abstract class B { ... }
private class C extends B { ... }
private class D extends B { ... }



I'm trying to simplify what the code looks like, to clarify the relationship between the classes. I tried to refactor it so it would look like this:

public class A {
    public static void main( String args[] ) {
        new A.B.C();
        new A.B.D();
    }

    private abstract class B {
        private class C extends B { ... }
        private class D extends B { ... }
    }
}



But this doesn't work -- I get errors that say "an enclosing instance that contains A.B.C is required," and "an enclosing instance that contains A.B.D is required." I'm not quite sure what I'm doing wrong here, would anyone mind pointing me in the right direction to make this work, please?

I know some people are probably going to skewer me for how I've designed these classes, but I'm designing them for a very large code base and they're all self-contained with each other, so my philosophy is, the fewer class files to bounce around, the better.

Thanks,
Zel2008
Was This Post Helpful? 0
  • +
  • -

#3 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2144
  • View blog
  • Posts: 3,296
  • Joined: 21-June 11

Re: Inner classes and enclosing instances

Posted 12 September 2011 - 09:33 AM

Your inner classes should be declared static. Otherwise you need an instance of A to instantiate them (non-static inner classes belong to an instance of the enclosing class, allowing them to access the fields and methods of the enclosing instance).

This post has been edited by sepp2k: 12 September 2011 - 09:36 AM

Was This Post Helpful? 0
  • +
  • -

#4 Zel2008  Icon User is offline

  • D.I.C Addict

Reputation: 14
  • View blog
  • Posts: 790
  • Joined: 06-January 09

Re: Inner classes and enclosing instances

Posted 12 September 2011 - 09:36 AM

Sorry sepp2k,
That first post was a mistake, I accidentally submitted it while typing. I know there are problems with it, the real code is the next post down.
Sorry!
Zel2008
Was This Post Helpful? 0
  • +
  • -

#5 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2144
  • View blog
  • Posts: 3,296
  • Joined: 21-June 11

Re: Inner classes and enclosing instances

Posted 12 September 2011 - 09:38 AM

Yes, I noticed that and trimmed my post down to the part that still applies to the fixed version.
Was This Post Helpful? 0
  • +
  • -

#6 Zel2008  Icon User is offline

  • D.I.C Addict

Reputation: 14
  • View blog
  • Posts: 790
  • Joined: 06-January 09

Re: Inner classes and enclosing instances

Posted 12 September 2011 - 09:42 AM

Thanks sepp2k,
I made the classes static, like this:

public class A {
    public static void main( String args[] ) {
        new C();
        new D();
    }
    abstract class B { ... }
    static class C extends B { ... }
    static class D extends B { ... }
}



But now I get errors saying that it doesn't know what C and D are (cannot find symbol: class C; cannot find symbol: class D). As far as I know you can't make an abstract class static, so would you mind telling me what I'm missing here? (Sorry if I sound a bit dense.)

Thanks,
Zel2008

This post has been edited by Zel2008: 12 September 2011 - 09:43 AM

Was This Post Helpful? 0
  • +
  • -

#7 GregBrannon  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2205
  • View blog
  • Posts: 5,239
  • Joined: 10-September 10

Re: Inner classes and enclosing instances

Posted 12 September 2011 - 09:44 AM

View PostZel2008, on 12 September 2011 - 12:30 PM, said:

I know some people are probably going to skewer me for how I've designed these classes, but I'm designing them for a very large code base and they're all self-contained with each other, so my philosophy is, the fewer class files to bounce around, the better.

Few people will skewer you for a good idea, but the 'good' in this idea - at least as you've explained it to us - is obscured by the complexity and resulting confusion. Simpler is better. The terms "large code base" and "many class files" don't have to mean complicated. If you apply OOP principles and maintain data encapsulation, complexity should be minimal, regardless the number of class files or lines of code.

As pointed out to me earlier today, keep in mind the poor sod that might have to someday change, fix, or reuse your code. Imagine yourself as that person (I know it's hard) coming at this code cold 3 years from now and consider how you'd change it to make it more understandable.
Was This Post Helpful? 0
  • +
  • -

#8 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2144
  • View blog
  • Posts: 3,296
  • Joined: 21-June 11

Re: Inner classes and enclosing instances

Posted 12 September 2011 - 09:48 AM

The code you gave will not cause the errors you describe. What it will cause (after removing the ...s which are syntax errors of course) is errors about the static classes C and D trying to inherit from the non-static class B.

Once we fix that by making B static (abstract class can be static just fine), the code compiles fine. Nothing whatsoever about missing symbols.
Was This Post Helpful? 0
  • +
  • -

#9 Zel2008  Icon User is offline

  • D.I.C Addict

Reputation: 14
  • View blog
  • Posts: 790
  • Joined: 06-January 09

Re: Inner classes and enclosing instances

Posted 12 September 2011 - 09:48 AM

Thanks GregBrannon,
If you think this is complex, that means I've messed up somewhere; I was trying to make things simpler. I have a nagging suspicion that I might be able to fuse B, C, and D into one class, which would make things much easier, but I haven't been able to do it successfully yet. In lieu of making lots of complex inner classes, do you have any ideas for simplifying these little classes into one?

	abstract class NumericField extends JTextField {
		protected NumericField( final Number defaultVal, final Number min,
		                        final Number max ) {
			setPreferredSize( new Dimension( 100, 25 ) );
			setText( defaultVal.toString() );
			addKeyListener( new KeyAdapter() {
				public void keyTyped( KeyEvent e ) {
					if( !checkValidInput( e.getKeyChar(), getText() ) ) {
						e.consume();
					}
				}
			});
			addFocusListener( new FocusAdapter() {
				public void focusLost( FocusEvent e ) {
					try {
						checkNumberValue( getText(), min, max, defaultVal );
					} catch( NumberFormatException ex ) {
						setText( defaultVal.toString() );
					}
				}
			});
		}

		protected abstract Number checkNumberValue( String text, Number min,
		                                            Number max, Number defaultVal )
			throws NumberFormatException;

		protected abstract boolean checkValidInput( char next, String text );

		static class IntegerField extends NumericField {
			public IntegerField( final Integer defaultVal ) {
				super( defaultVal, Integer.MAX_VALUE * -1, Integer.MAX_VALUE );
			}

			public IntegerField( final Integer defaultVal, final Integer min,
			                     final Integer max ) {
				super( defaultVal, min, max );
			}

			protected Number checkNumberValue( String text, Number min, Number max, Number defaultVal )
				throws NumberFormatException {
				Integer value = Integer.parseInt( text );
				if( value.compareTo( min.intValue() ) < 0 ) { throw new NumberFormatException(); }
				if( value.compareTo( max.intValue() ) > 0 ) { throw new NumberFormatException(); }
				return value;
			}

			protected boolean checkValidInput( char next, String text ) {
				boolean negativeStart =
					( text.length() == 0 ) &&
					( !text.contains( "-" ) ) &&
					( next == '-' );

				boolean valid =
					Character.isDigit( next ) ||
					negativeStart;

				return valid;
			}
		}

		static class DoubleField extends NumericField {
			public DoubleField( final Double defaultVal ) {
				super( defaultVal, Double.MAX_VALUE * -1, Double.MAX_VALUE );
			}
		
			public DoubleField( final Double defaultVal, final Double min,
			                    final Double max ) {
				super( defaultVal, min, max );
			}

			protected Number checkNumberValue( String text, Number min, Number max, Number defaultVal )
				throws NumberFormatException {
				Double value = Double.parseDouble( text );
				if( value.compareTo( min.doubleValue() ) < 0 ) { throw new NumberFormatException(); }
				if( value.compareTo( max.doubleValue() ) > 0 ) { throw new NumberFormatException(); }
				return value;
			}
		
			protected boolean checkValidInput( char next, String text ) {
				boolean negativeStart =
					( text.length() == 0 ) &&
					( !text.contains( "-" ) ) &&
					( next == '-' );

				boolean decimalPoint =
					( text.length() > 0 ) &&
					( !text.contains( "." ) ) &&
					( !text.equals( "-" ) ) &&
					( next == '.' );

				boolean valid =
					Character.isDigit( next ) ||
					negativeStart ||
					decimalPoint;
			
				return valid;
			}
		}
	}



Thanks,
Zel2008
Was This Post Helpful? 0
  • +
  • -

#10 GregBrannon  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2205
  • View blog
  • Posts: 5,239
  • Joined: 10-September 10

Re: Inner classes and enclosing instances

Posted 12 September 2011 - 10:25 AM

To be clear, the code above has one class, NumericField, which is an extension of JTextField. Added to your JTextField, NumericField, are a KeyListener and a FocusListener which are implemented using anonymous inner classes. Adding listeners using anonymous inner classes is the approach recommended by 9 out of 10 dentists, but I have no actual data to support that.

I don't know how it could be written to be any simpler, but I can understand how it might appear complex to someone who is unfamiliar with what is being done.
Was This Post Helpful? 0
  • +
  • -

#11 Zel2008  Icon User is offline

  • D.I.C Addict

Reputation: 14
  • View blog
  • Posts: 790
  • Joined: 06-January 09

Re: Inner classes and enclosing instances

Posted 12 September 2011 - 10:49 AM

Thanks everyone,
I realized this entire way I was doing things was far too complex, and I'm working on recoding it. Thanks for the help and ideas, I really appreciate them.
Thanks,
Zel2008
Was This Post Helpful? 0
  • +
  • -

#12 cmpshr  Icon User is offline

  • D.I.C Head

Reputation: 42
  • View blog
  • Posts: 120
  • Joined: 22-August 11

Re: Inner classes and enclosing instances

Posted 12 September 2011 - 02:08 PM

View PostGregBrannon, on 12 September 2011 - 10:25 AM, said:

Adding listeners using anonymous inner classes is the approach recommended by 9 out of 10 dentists, but I have no actual data to support that.

May be dentits but surely not Java programmers :)
Would be interesting to actually have data about that.
Personnaly I think that anonymous inner classes add too many lines of code in constructors.
Was This Post Helpful? 0
  • +
  • -

#13 GregBrannon  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2205
  • View blog
  • Posts: 5,239
  • Joined: 10-September 10

Re: Inner classes and enclosing instances

Posted 12 September 2011 - 02:36 PM

View Postcmpshr, on 12 September 2011 - 05:08 PM, said:

May be dentits but surely not Java programmers :)
Personnaly I think that anonymous inner classes add too many lines of code in constructors.

On small example programs of the kind used for learning and practice, the anonymous inner class listener construct is often found in the GUI's constructor, but it doesn't have to be there. On larger, more complex GUIs with a number of sub-containers, each containing a number of components, I would recommend that the GUI's sub-containers are constructed separately in their own methods. If the GUI is really complex, made up of more than a couple sub-containers, then it should be assembled by yet another method. The class' constructor then creates the entire GUI to be presented to the user with a single call to the buildMainFramePanel() method. Roughly, following the model below, adjusted or scaled as appropriately for the GUI's complexity:

public class MainFrame
{
    protected JFrame mainFrame = new JFrame( "Main Frame" );

    // constructor
    public MainFrame()
    {
        mainFrame.add( buildMainFramePanel() );
        // other frame housekeeping statements, as necessary
        mainFrame.setVisible( true );
    }

    private JPanel buildMainFramePanel()
    {
        JPanel mainPanel = new JPanel();

        // builds the frame's GUI out of the necessary parts
        mainPanel.add( panelOne );
        mainPanel.add( panelTwo );
        //  . . . . etc.

        return mainPanel;
    }

    // other JPanel methods as necessary for building the mainPanel
    private JPanel panelOne()
    {
        // sub-panel one is constructed here with the necessary
        // components and listeners (using anonymous inner classes?)
    }

    private JPanel panelTwo()
    {
        // sub-panel two is constructed here with the necessary
        // components and listeners (using anonymous inner classes?)
    }

} // end class MainFrame

This post has been edited by GregBrannon: 12 September 2011 - 02:37 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1