Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialVladislav Kobyakov
9,439 PointsWhy am I able to access the list of videos that is private?
My question is why can I access and alter the private member property mVideos from the "Course" class? My original understanding was that since it's been declared as "private" I shouldn't be able to change it unless there is a "setter" method. In this challenge there is only the getVideos() method, but I can still add a video using "course.getVideos().add(1 , video). Will I also be able to remove an element from this list using "coures.getVideos().remove(someIndex)"? I guess I need a bit more explanation on this. Could somebody explain it to me?
Code:
import com.example.model.Course;
import com.example.model.Video;
import java.util.Map;
public class QuickFix {
public void addForgottenVideo(Course course) {
List<Video> videoList = course.getVideos(); //Formal step. Can be solved without this.
// TODO(1): Create a new video called "The Beginning Bits"
Video vid = new Video("The Beginning Bits");
// TODO(2): Add the newly created video to the course videos as the second video.
videoList.add(1, vid); //first solution
course.getVideos().add(1, vid); //second solution
}
public void fixVideoTitle(Course course, String oldTitle, String newTitle) {
}
public Map<String, Video> videosByTitle(Course course) {
return null;
}
}
package com.example.model;
public class Video {
private String mTitle;
public Video(String title) {
mTitle = title;
}
public String getTitle() {
return mTitle;
}
public void setTitle(String title) {
mTitle = title;
}
}
package com.example.model;
import java.util.List;
public class Course {
private String mName;
private List<Video> mVideos;
public Course(String name, List<Video> videos) {
mName = name;
mVideos = videos;
}
public String getName() {
return mName;
}
public List<Video> getVideos() {
return mVideos;
}
}
3 Answers
Chris Tvedt
3,795 PointsHi Vladislav,
You ask a good question. I would imagine that this has to do with the fact that the "List" interface is a public interface with its own default modifier methods.
To make it truly "read-only" you will need to use the "Collections.unModifiableList()" method to return an unmodifiable list.
The "private" modifier just means you can not Directly access the variables. But through other methods you might be able too.
example:
//Setting up a list of videos and a course.
List<Video> videos = new List<>();
videos.add(new Video("This is a new video");
Course newCourse = new Course("course", videos);
You would not be able to do:
newCourse.getVideos().getIndex(0).mTitle = "Trying change title on chosen video";
Because you are not allowed to access the mTitle directly. But you could to it through a setter-method.
That is what is being done in the case of adding to the list. you are accessing the list variables through the "List"-interfaces methods.
This is atleast how i understand it to work and it makes sense in my head.
If someone finds this information to be complete BS, please let me know so i can remove it from the forum.
Please "Up-vote" if this helped you in any way.
Chris.
Chris Tvedt
3,795 PointsHi again Vladislav,
If you try running the following code to test your classes
public class Testing {
public static void main(String[] args) {
//Setting up a list of videos and a course.
List<Video> videos = new ArrayList<>();
videos.add(new Video("This is a new video");
Course newCourse = new Course("course", videos);
//this does not work with mTitle being private.
newCourse.getVideos().get(0).mTitle = "Trying change title on chosen video";
//but if you now change mTitle to be public, you can edit it directly. Thats the purpose of the private modifier.
}
}
You will now see that if you change the modifier on mTitle to public, you can change the title directly, if its private, you have to go through another method, a setter or through a method in the List-class.
A modifier is just so that you can or can not access a variable/method directly, but you might be able to in-directly, through another method. Like setters and alike.
Did this make it clearer? :-)
Chris
Vladislav Kobyakov
9,439 PointsI actually meant if we change the type modifier of the list mVideos
and not the mTitle
. It seems to be the case that the ArrayList
is always mutable so that's why one should always put additional restrictions on the getter method to make it of "read-only" type... Of course if you change the type modifier for mTitle
from private to public, you can access and change it from any other class.
My only concern here was that the list mVideos
declared as private
doesn't do much as it would be equally accessible from other classes (only the list, not any particular object in the list or that object's member variable) if it was declared as public
.
Thanks again for your reply! :)
Chris Tvedt
3,795 PointsI see your point, and yes, if you want full imutability on your list, you will have to use the unModifiableList()-method.
Chris Tvedt
3,795 PointsI think you are mixing the "private"modifier with the "final" keyword. Final makes a variable "un-editable". The "private" just makes it so you cannot access the variable outside the class.
private: can be altered (if not final) but cannot be accessed directly outside its own class.
public: can be altered (if not final) and can be accessed outside its own class.
protected: can be altered (if not final) and can be accesses outside its own class if
the classes are in the same package. or if it is a subclass of the protected class.
Hope this made things a little clearer. Please up-vote if they did :-)
Chris
Vladislav Kobyakov
9,439 PointsHello Chris! I've just added the missing code from the challenge and the solution possibilities for the first (out of 3 in total) task. So when I solve it I actually access and modify the private variable of class "Course" from the class "QuickFix". Although I can access and view the list because I'm provided with the public List<Video> getVideos();
method, why am I able to modify it directly from a different class "QuickFix" if it is declared as private?
Chris Tvedt
3,795 PointsHi Vladislav,
Posten an answer below.
Vladislav Kobyakov
9,439 PointsVladislav Kobyakov
9,439 PointsThanks Chris! It makes more sense now, but now I don't really understand what's the privilege of declaring the
List<Video> mVideos
asprivate
. Since any other class have full access over themVideos
list and any element can be removed usingsomeCourse.getVideos().remove(someIndex)
or can be added usingsomeCourse.getVideos().add(someVideo)
. Does that mean that thegetVideos()
method breaks the encapsulation of the list itself (or any other container in a different situation) and always has to returnCollections.unmodifiableList(mVideos)
(or an alternative method for another container type) if intended to be of READ ONLY type?I've just checked if I declare the
List<Video> mVideos
from theCourse
class aspublic
I also can't access a certain title from a certain video from the list as you've mentioned before usingsomeCourse.getVideos().get(someIndex).mTitle
. So this brings me back to the question what does theprivate
type modifier do in this situation at all if thegetVideos()
method lets any class do anything it wants?