Domanda

We have two Classes (one parent and a child). both uses private variables to store values, but the parent should NOT provide setters (x and y are given with the constructor and they are some sort of immutable). B should extend A with setters for x and y. Is there a common way to do so?

class A{
    private int x;
    private int y;

    A(int x, int y){
        this.x = x;
        this.y = y;
    }

}

class B extends A{

    public void setx(int x){
        this.x = x;
    }

    //same for y
}

Some thoughts

  • variables should be private
  • x and y of parent have to be immutable
  • B has to provide a public setter
È stato utile?

Soluzione

If you want the variables to be immutable then it should be

class B extends A{

    public B(int x, int y){
          super(x, y);
    }
}

At the moment your x and y variables in A are not immutable. To make them immutable then precede them with final

This is the only way you can assign x and y as they are private. If you want setters then you will have to make the variables protected.

Personally I am a big fan of immutability so would do this rather than setters - creating objects is usually quite cheap.

Altri suggerimenti

Declare the variables as protected in the base class and write getter and setter in the child classes.

You can't have a private member variable and no method (here with method I mean also the constructor) setting it (well, technically you can, but it does not make sense). If you want your variables to be settable from a derived class, they have to be protected.

EDIT: You can, however, define a protected "helper" setter in the base class and call this protected helper setter from a public setter in the derived class.

SECOND EDIT: Another possibility is defining an abstract getter in the base class and implement getter, setter, as well as the private field, in the derived class (template pattern).

This is a weird question, immutable but mutable, private but public... The correct way should be to make them protected, as everyone said.

Anyway, in java you can use dirty tricks if the security manager doesn't complain, check this out:

import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Priv
{
    public static class A
    {
        private final int x;
        public A(int x)
        {
            this.x = x;
        }
    }

    public static class B extends A
    {
        public B(int x)
        {
            super(x);
        }

        public void setX(int x)
        {
            Class c = A.class;
            try
            {
                 Field f = c.getDeclaredField("x");
                f.setAccessible(true);
                f.set(this, x);
            } catch (IllegalArgumentException ex) {
                Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
            } catch (NoSuchFieldException ex) {
                Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SecurityException ex) {
                Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        public int getX()
        {
            int v = 0;

            try {
                Class c = A.class;
                Field f = c.getDeclaredField("x");
                f.setAccessible(true);
                v = f.getInt(this);
            } catch (IllegalArgumentException ex) {
                Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
            } catch (NoSuchFieldException ex) {
                Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SecurityException ex) {
                Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
            }

            return v;
        }
    }

    public static void main(String[] args)
    {
         B b = new B(5);

         System.out.println("b.x is " + b.getX());

         b.setX(42);

        System.out.println("b.x now is " + b.getX());
    }

}

There is no concept of immutable is you have any setter method or constructor of child class calling super to re-initialize the variable of super class which are private.

immutable is inherently thread-safe.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top