26.컬렉션 캡슐화 Encapsulate Collection
Before
class Person
{
public List < Course > Course { get ; set ; }
}
class Course
{
public string Name { get ; set ; }
public bool IsAdvanced { get ; set ; }
}
class Simple_Example
{
public void ManipulatingCourses ()
{
var kent = new Person () { Course = new List < Course >() };
kent . Course . Add ( new Course { Name = "Smalltalk Programming" , IsAdvanced = false });
kent . Course . Add ( new Course { Name = "Appreciating Single Malts" , IsAdvanced = true });
var refactoringCourse = new Course { Name = "Refactioring" , IsAdvanced = false };
kent . Course . Add ( refactoringCourse );
kent . Course . Add ( new Course { Name = "Brutal Sarcasm" , IsAdvanced = true });
kent . Course . Remove ( refactoringCourse );
}
public void Getting ()
{
var kent = new Person ();
// more code
var advencedCourses = kent . Course . Count ( c => c . IsAdvanced );
}
}
컬렉션을 리턴하는 메소드가 있으면 그 메소드가 읽기전용 뷰를 리턴하도록 만들고, add/remove 메소드를 제공하라.
get 메소드가 컬렉션 자체를 리턴하면 안된다. 이유는 클라이언트 코드가 컬렉션을 가지고 있는 클래스가 알지 못하는 사이에 컬렉션의 내용을 조작할 수 있기 때문이다. get 메소드는 컬렉션을 조작하지 못하도록 하여 리턴 해야 한다.
또한 set 메소드도 있으면 안 된다. 대신 컬렉션의 요소를 추가, 삭제하는 작업을 제어할 수 있게 된다.
After
class Person
{
private List < Course > _courses ;
public IReadOnlyList < Course > Courses // 읽기 전용 collection
{
get { return _courses . AsReadOnly (); } // 현재 collection에 대한 읽기 전용 list 반환
}
public Person ()
{
_courses = new List < Course >();
}
//public Person(IEnumerable<Course> courses) 기본 타입 생성자 동시에 실행
// :this()
//{
// _courses.AddRange(courses);
//}
public void AddCourse ( Course course ) // add 메소드 제공
{
_courses . Add ( course );
}
public void RemoveCourse ( Course course ) // remove 메소드 제공
{
_courses . Remove ( course );
}
}
class Course
{
public string Name { get ; set ; }
public bool IsAdvanced { get ; set ; }
}
class Simple_Example
{
public void ManipulatingCourses ()
{
var kent = new Person ();
kent . AddCourse ( new Course { Name = "Smalltalk Programming" , IsAdvanced = false });
kent . AddCourse ( new Course { Name = "Appreciating Single Malts" , IsAdvanced = true });
var refactoringCourse = new Course { Name = "Refactioring" , IsAdvanced = false };
kent . AddCourse ( refactoringCourse );
kent . AddCourse ( new Course { Name = "Brutal Sarcasm" , IsAdvanced = true });
kent . RemoveCourse ( refactoringCourse );
}
public void Getting ()
{
var kent = new Person ();
// more code
var advencedCourses = kent . Courses . Count ( c => c . IsAdvanced );
}
}