Jump to content

Encapsulation question regarding ArrayLists

- - - - -

  • Please log in to reply
7 replies to this topic

#1
LDM91

LDM91

    Newbie

  • Members
  • Pip
  • 3 posts
Hi there. I've been working on a side project outside of class (I'm a Software Engineering student at Uni) which is really just a simple Banking system to help my understanding of Java. Basically the program reads existing accounts from a .txt file which are then placed into an ArrayList (they are split into Account objects).

The user can then choose to create a new account which added to the ArrayList or edit an existing one. I have three classes - the main class, Account class and UserInterface class. The main class holds all the methods such as SaveAccount (writes the accounts into file) etc. the Account class defines the account and then the UserInterface produces a UI to the user and interacts with them. The problem is I have the ArrayList in the main class and the only way to access it in UserInface is through making it public. My lecturer said this is bad since then the UserInterface class can edit it which I don't want. The thing is though I can't make the Account methods private as I want to edit them until they are put into the ArrayList so I'm not sure how to do it.

My only theory is copying the object to a duplicate class which has private settings before throwing it into the ArrayList. Would this work/be the best solution? Sorry if my question is long winded, I'll try to make it more concise if necessary.

#2
nadun

nadun

    Newbie

  • Members
  • Pip
  • 6 posts
Hi LDM91

In your banking application in object oriented design perspective it's not a good idea to define lots of methods such as SaveAccount in the Main class. You could have define a class called Customer and put methods such as Withdraw and CreditAccount inside that class. As your teacher mentioned instance variables shouldn't be public. It's not a good design practice. Other clients can misuse it. Have you heard about getters and setters.? You can make instance variables private and use getters and setters to access and validate those instance variables.
Hope this will help you.

Cheers

#3
wim DC

wim DC

    Writes binary right handed and hex left handed

  • Members
  • PipPipPipPipPipPipPipPipPip
  • 2,084 posts
  • Programming Language:Java, JavaScript, PL/SQL
  • Learning:Java
You can make a getter in the Account class:
public List getAccounts(){
  return Collections.unmodifiableList(arrayListName);
}

The unmodifiableList function returns a List, so you can do list.get(0) on it. You can also do list.remove(0);
It won't give errors on compiling, but if that code is executed it will throw an error because you can't edit an unmodifiablelist.

#4
LDM91

LDM91

    Newbie

  • Members
  • Pip
  • 3 posts
Thank you both for the replies.

RE: reply 1:

I think I got a bit confused as I have the getter and setters in their respective classes, so it is slightly duplicated in a way I guess. The only reason I had lots of methods in the main was because I am scanning the input from the user and not just doing Account.SetID(1) for example.


RE: reply 2:

I understand what you're suggesting but I'm sure it is right to use it? As the ArrayList is an ArrayList of Account objects I'm not sure how setting that method is suitable here. Sorry if I have misunderstood.

#5
wim DC

wim DC

    Writes binary right handed and hex left handed

  • Members
  • PipPipPipPipPipPipPipPipPip
  • 2,084 posts
  • Programming Language:Java, JavaScript, PL/SQL
  • Learning:Java
Because ArrayList extends List, there is no problem in converting an ArrayList into a List;

List<String> myList =  new ArrayList<String>();
Works without errors and myList will behave just like an ArrayList.

If you really want your ArrayList back you can cast it
ArrayList<String> myList = (ArrayList<String>) Collections.unmodifiableList(otherList);
But that shouldn't be really necessary.

#6
ZekeDragon

ZekeDragon

    Writes binary right handed and hex left handed

  • Moderators
  • 2,103 posts
You could make a subclass of ArrayList and have it implement an interface of your creation, that only defines the getting methods of the class, thus excluding the other methods from the returned object. Consider the following:
public interface NoModifyArrayList<E> extends Iterable<E>
{
    boolean contains(Object o);
    E get(int x);
    int indexOf(Object o);
    boolean isEmpty();
    int lastIndexOf(Object o);
    int size();
}
import java.util.ArrayList;
import java.util.Iterator;

public class SubArrayList<E> extends ArrayList<E> implements NoModifyArrayList<E>
{
    // Everything is pretty much done except that NoModifyArrayList extends 
    // Iterable, which defines the iterator method. This method IS defined in
    // ArrayList, so I could leave it as be, but this iterator can modify the
    // list using remove(), so I have to have a new Iterator which works just
    // like the ArrayList iterator except it throws 
    // UnsupportedOperationException upon use of remove().

    private class NoModIterator implements Iterator<E>
    {
        public NoModIterator(Iterator<E> it) { this.it = it; }
        public boolean hasNext() { return it.hasNext(); }
        public E next() { return it.next(); }
        public void remove() { throw new UnsupportedOperationException(); }
        private Iterator<E> it;
    }

    public Iterator<E> iterator() { return new NoModIterator(super.iterator()); }
}
What I provided was only an example, you should make SubArrayList a private class of your Accounts class to contain all the loaded Account information, where you can write to SubArrayList. Then, you have your method return a NoModifyArrayList and just return your SubArrayList class, the compiler will enforce that the returned interface object could not have access to any modifying methods.
Wow I changed my sig!

#7
LDM91

LDM91

    Newbie

  • Members
  • Pip
  • 3 posts
Thank you for the help. I will try what you have suggested later today and report back if I have any problems!

#8
wim DC

wim DC

    Writes binary right handed and hex left handed

  • Members
  • PipPipPipPipPipPipPipPipPip
  • 2,084 posts
  • Programming Language:Java, JavaScript, PL/SQL
  • Learning:Java

ZekeDragon said:

You could make a subclass of ArrayList and have it implement an interface of your creation, that only defines the getting methods of the class, thus excluding the other methods from the returned object. Consider the following:
public interface NoModifyArrayList<E> extends Iterable<E>
{
    boolean contains(Object o);
    E get(int x);
    int indexOf(Object o);
    boolean isEmpty();
    int lastIndexOf(Object o);
    int size();
}
import java.util.ArrayList;
import java.util.Iterator;

public class SubArrayList<E> extends ArrayList<E> implements NoModifyArrayList<E>
{
    // Everything is pretty much done except that NoModifyArrayList extends 
    // Iterable, which defines the iterator method. This method IS defined in
    // ArrayList, so I could leave it as be, but this iterator can modify the
    // list using remove(), so I have to have a new Iterator which works just
    // like the ArrayList iterator except it throws 
    // UnsupportedOperationException upon use of remove().

    private class NoModIterator implements Iterator<E>
    {
        public NoModIterator(Iterator<E> it) { this.it = it; }
        public boolean hasNext() { return it.hasNext(); }
        public E next() { return it.next(); }
        public void remove() { throw new UnsupportedOperationException(); }
        private Iterator<E> it;
    }

    public Iterator<E> iterator() { return new NoModIterator(super.iterator()); }
}
What I provided was only an example, you should make SubArrayList a private class of your Accounts class to contain all the loaded Account information, where you can write to SubArrayList. Then, you have your method return a NoModifyArrayList and just return your SubArrayList class, the compiler will enforce that the returned interface object could not have access to any modifying methods.

That's exactly what Collections.unmodifiableList does.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users