Java OOP - Composition

Có hai cách để sử dụng lại các lớp hiện có, đó là thành phần và kế thừa . Với thành phần (còn gọi là tổng hợp ), bạn định nghĩa một lớp mới, bao gồm các lớp hiện có. Với tính kế thừa , bạn lấy được một lớp mới dựa trên một lớp hiện có, với các sửa đổi hoặc phần mở rộng.

1.  Composition - Thành Phần

Chúng ta sẽ bắt đầu với việc sử dụng lại các lớp thông qua thành phần - với các ví dụ sau:

1.1  Composition EG. 1: The Author and Book Classes

OOP_AuthorClass.png
Author Class (Author.java)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/** 
 * The Author class model a book's author.
 */
public class Author {
   // The private instance variables
   private String name;
   private String email;
   private char gender;   // 'm' or 'f'
 
   /** Constructs a Author instance with the given inputs */
   public Author(String name, String email, char gender) {
      this.name = name;
      this.email = email;
      this.gender = gender;
   }
 
   // The public getters and setters for the private instance variables.
   // No setter for name and gender as they are not designed to be changed.
   /** Returns the name */
   public String getName() {
      return name;
   }
   /** Returns the gender */
   public char getGender() {
      return gender;
   }
   /** Returns the email */
   public String getEmail() {
      return email;
   }
   /** Sets the email */
   public void setEmail(String email) {
      this.email = email;
   }
 
   /** Returns a self-descriptive String */
   public String toString() {
      return name + " (" + gender + ") at " + email;
   }
}
TestAuthor.java
/**
 * A test driver for the Author class.
 */
public class TestAuthor {
   public static void main(String[] args) {
      // Test constructor and toString()
      Author ahTeck = new Author("Tan Ah Teck", "teck@nowhere.com", 'm');
      System.out.println(ahTeck);  // toString()
      //Tan Ah Teck (m) at teck@nowhere.com

      // Test Setters and Getters
      ahTeck.setEmail("teck@somewhere.com");
      System.out.println(ahTeck);  // toString()
      //Tan Ah Teck (m) at teck@somewhere.com
      System.out.println("name is: " + ahTeck.getName());
      //name is: Tan Ah Teck
      System.out.println("gender is: " + ahTeck.getGender());
      //gender is: m
      System.out.println("email is: " + ahTeck.getEmail());
      //email is: teck@somewhere.com
   }
}
Một cuốn sách Book được viết bởi một Author - Sử dụng "Object" Member Variable (biến thành phần là một đối tượng)
OOP_BookClass.png

Book Class (Book.java)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
 * The Book class models a book with one (and only one) author.
 */
public class Book {
   // The private instance variables
   private String name;
   private Author author;
   private double price;
   private int qty;
 
   /** Constructs a Book instance with the given author */
   public Book(String name, Author author, double price, int qty) {
      this.name = name;
      this.author = author;
      this.price = price;
      this.qty = qty;
   }
 
   // Getters and Setters
   /** Returns the name of this book */
   public String getName() {
      return name;
   }
   /** Return the Author instance of this book */
   public Author getAuthor() {
      return author;  // return member author, which is an instance of the class Author
   }
   /** Returns the price */
   public double getPrice() {
      return price;
   }
   /** Sets the price */
   public void setPrice(double price) {
      this.price = price;
   }
   /** Returns the quantity */
   public int getQty() {
      return qty;
   }
   /** Sets the quantity */
   public void setQty(int qty) {
      this.qty = qty;
   }
 
   /** Returns a self-descriptive String */
   public String toString() {
      return "'" + name + "' by " + author;  // author.toString()
   }
}
Book Class (TestBook.java)
/**
 * A test driver program for the Book class.
 */
public class TestBook {
   public static void main(String[] args) {
      // We need an Author instance to create a Book instance
      Author ahTeck = new Author("Tan Ah Teck", "ahTeck@somewhere.com", 'm');
      System.out.println(ahTeck);  // Author's toString()
      //Tan Ah Teck (m) at ahTeck@somewhere.com

      // Test Book's constructor and toString()
      Book dummyBook = new Book("Java for dummies", ahTeck, 9.99, 99);
      System.out.println(dummyBook);  // Book's toString()
      //'Java for dummies' by Tan Ah Teck (m) at ahTeck@somewhere.com

      // Test Setters and Getters
      dummyBook.setPrice(8.88);
      dummyBook.setQty(88);
      System.out.println("name is: " + dummyBook.getName());
      //name is: Java for dummies
      System.out.println("price is: " + dummyBook.getPrice());
      //price is: 8.88
      System.out.println("qty is: " + dummyBook.getQty());
      //qty is: 88
      System.out.println("author is: " + dummyBook.getAuthor());  // invoke Author's toString()
      //author is: Tan Ah Teck (m) at ahTeck@somewhere.com
      System.out.println("author's name is: " + dummyBook.getAuthor().getName());
      //author's name is: Tan Ah Teck
      System.out.println("author's email is: " + dummyBook.getAuthor().getEmail());
      //author's email is: ahTeck@somewhere.com
      System.out.println("author's gender is: " + dummyBook.getAuthor().getGender());
      //author's gender is: m

      // Using an anonymous Author instance to create a Book instance
      Book moreDummyBook = new Book("Java for more dummies",
            new Author("Peter Lee", "peter@nowhere.com", 'm'), // an anonymous Author's instance
            19.99, 8);
      System.out.println(moreDummyBook);  // Book's toString()
      //'Java for more dummies' by Peter Lee (m) at peter@nowhere.com
   }
}
Lưu ý: Trong ví dụ này, tôi đã sử dụng " name" cho Booklớp thay vì " title" để minh họa rằng bạn có thể có một biến nametrong cả lớp Authorvà Booklớp, nhưng chúng khác biệt.

1.2  Composition EG. 2: Point và Line Classes

class diagram

OOP_CompositionLinePointDetails.png
 Line Class via Composition (Line.java)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
 * A Line composes of two Points - a begin "Point" and an end "Point".
 * We reuse the Point class via composition.
 */
public class Line {
   // The private instance variables
   Point begin, end;   // instances of the "Point" class
 
   /** Constructs a Line instance given 2 points at (x1, y1) and (x2, y2) */
   public Line(int x1, int y1, int x2, int y2) {
      begin = new Point(x1, y1);  // Construct the instances declared
      end   = new Point(x2, y2);
   }
   /** Construct a Line instance given 2 Point instances */
   public Line(Point begin, Point end) {
      this.begin = begin;  // The caller had constructed the instances
      this.end   = end;
   }
 
   // The public getter and setter for the private instance variables
   public Point getBegin() {
      return begin;
   }
   public Point getEnd() {
      return end;
   }
   public void setBegin(Point begin) {
      this.begin = begin;
   }
   public void setEnd(Point end) {
      this.end = end;
   }
 
   public int getBeginX() {
      return begin.getX();  // Point's getX()
   }
   public void setBeginX(int x) {
      begin.setX(x);  // Point's setX()
   }
   public int getBeginY() {
      return begin.getY();  // Point's getY()
   }
   public void setBeginY(int y) {
      begin.setY(y);  // Point's setY()
   }
   public int[] getBeginXY() {
      return begin.getXY();  // Point's getXY()
   }
   public void setBeginXY(int x, int y) {
      begin.setXY(x, y);  // Point's setXY()
   }
   public int getEndX() {
      return end.getX();  // Point's getX()
   }
   public void setEndX(int x) {
      end.setX(x);  // Point's setX()
   }
   public int getEndY() {
      return end.getY();  // Point's getY()
   }
   public void setEndY(int y) {
      end.setY(y);  // Point's setY()
   }
   public int[] getEndXY() {
      return end.getXY();  // Point's getXY()
   }
   public void setEndXY(int x, int y) {
      end.setXY(x, y);  // Point's setXY()
   }
 
   /** Returns a self-descriptive String */
   public String toString() {
      return "Line[begin=" + begin + ",end=" + end + "]";
            // Invoke begin.toString() and end.toString()
   }
 
   /** Returns the length of this line */
   public double getLength() {
      return begin.distance(end);  // use Point's distance() method
   }
}
TestLine.java
import java.util.Arrays;
/**
 * A Test Driver for the Line class.
 */
public class TestLine {
   public static void main(String[] args) {
      // Test constructor and toString()
      Line l1 = new Line(1, 2, 3, 4);
      System.out.println(l1);  // Line's toString()
      //Line[begin=(1,2),end=(3,4)]
      Line l2 = new Line(new Point(5,6), new Point(7,8));  // anonymous Point's instances
      System.out.println(l2);  // Line's toString()
      //Line[begin=(5,6),end=(7,8)]

      // Test Setters and Getters
      l1.setBegin(new Point(11, 12));
      l1.setEnd(new Point(13, 14));
      System.out.println(l1);  // Line's toString()
      //Line[begin=(11,12),end=(13,14)]
      System.out.println("begin is: " + l1.getBegin());  // Point's toString()
      //begin is: (11,12)
      System.out.println("end is: " + l1.getEnd());  // Point's toString()
      //end is: (13,14)

      l1.setBeginX(21);
      l1.setBeginY(22);
      l1.setEndX(23);
      l1.setEndY(24);
      System.out.println(l1);  // Line's toString()
      //Line[begin=(21,22),end=(23,24)]
      System.out.println("begin's x is: " + l1.getBeginX());
      //begin's x is: 21
      System.out.println("begin's y is: " + l1.getBeginY());
      //begin's y is: 22
      System.out.println("end's x is: " + l1.getEndX());
      //end's x is: 23
      System.out.println("end's y is: " + l1.getEndY());
      //end's y is: 24

      l1.setBeginXY(31, 32);
      l1.setEndXY(33, 34);
      System.out.println(l1);  // Line's toString()
      //Line[begin=(31,32),end=(33,34)]
      System.out.println("begin's x and y are: " + Arrays.toString(l1.getBeginXY()));
      //begin's x and y are: [31, 32]
      System.out.println("end's x and y are: " + Arrays.toString(l1.getEndXY()));
      //end's x and y are: [33, 34]

      // Test getLength()
      System.out.printf("length is: %.2f%n", l1.getLength());
      //length is: 2.83
   }
}
Exercise: Try writing these more complex methods for the Line class:
// Return the gradient of this line in radian (use Math.atan2(y, x)).
public double getGradient()

// Return the distance from this line to the given point.
public double distance(int x, int y)
public double distance(Point p)

// Return true if this line intersects the given line.
public boolen intersects(Line another)

1.3  Composition EG. 3:  Point và Circle Classes

OOP_MyPoint.png
ClassDiagram_CirclePoint.png
Circle class (Circle.java)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/**
 * The Circle class composes a "Point" instance as its center and a radius.
 * We reuse the "Point" class via composition.
 */
public class Circle {
   // The private member variables
   private Point center;  // Declare an instance of the "Point" class
   private double radius;
 
   // Constructors
   /** Constructs a Circle instance with the default values */
   public Circle() {
      this.center = new Point(); // Construct a Point at (0,0)
      this.radius = 1.0;
   }
   /** Constructs a Circle instance with the center at (xCenter, yCenter) and radius */
   public Circle(int xCenter, int yCenter, double radius) {
      center = new Point(xCenter, yCenter); // Construct a Point at (xCenter,yCenter)
      this.radius = radius;
   }
   /** Constructs a Circle instance with the given Point instance as center and radius */
   public Circle(Point center, double radius) {
      this.center = center;  // The caller had constructed a Point instance
      this.radius = radius;
   }
 
   // Getters and Setters
   public double getRadius() {
      return this.radius;
   }
   public void setRadius(double radius) {
      this.radius = radius;
   }
   public Point getCenter() {
      return this.center;  // return a Point instance
   }
   public void setCenter(Point center) {
      this.center = center;
   }
 
   public int getCenterX() {
      return center.getX();  // Point's getX()
   }
   public void setCenterX(int x) {
      center.setX(x);  // Point's setX()
   }
   public int getCenterY() {
      return center.getY();  // Point's getY()
   }
   public void setCenterY(int y) {
      center.setY(y);  // Point's setY()
   }
   public int[] getCenterXY() {
      return center.getXY();  // Point's getXY()
   }
   public void setCenterXY(int x, int y) {
      center.setXY(x, y);  // Point's setXY()
   }
 
   /** Returns a self-descriptive String */
   public String toString() {
      return "Circle[center=" + center + ",radius=" + radius + "]";  // invoke center.toString()
   }
 
   /** Returns the area of this circle */
   public double getArea() {
      return Math.PI * radius * radius;
   }
 
   /** Returns the circumference of this circle */
   public double getCircumference() {
      return 2.0 * Math.PI * radius;
   }
 
   /** Returns the distance from the center of this circle to the center of
       the given Circle instance called another */
   public double distance(Circle another) {
      return center.distance(another.center);  // Use distance() of the Point class
   }
 }
TestCircle.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
 * A test driver for the Circle class.
 */
public class TestCircle {
   public static void main(String[] args) {
      // Test Constructors and toString()
      Circle c1 = new Circle();
      System.out.println(c1);  // Circle's toString()
      Circle c2 = new Circle(1, 2, 3.3);
      System.out.println(c2);  // Circle's toString()
      Circle c3 = new Circle(new Point(4, 5), 6.6);   // an anonymous Point instance
      System.out.println(c3);  // Circle's toString()

      // Test Setters and Getters
      c1.setCenter(new Point(11, 12));
      c1.setRadius(13.3);
      System.out.println(c1);  // Circle's toString()
      System.out.println("center is: " + c1.getCenter());  // Point's toString()
      System.out.println("radius is: " + c1.getRadius());

      c1.setCenterX(21);
      c1.setCenterY(22);
      System.out.println(c1);  // Circle's toString()
      System.out.println("center's x is: " + c1.getCenterX());
      System.out.println("center's y is: " + c1.getCenterY());
      c1.setCenterXY(31, 32);
      System.out.println(c1);  // Circle's toString()
      System.out.println("center's x is: " + c1.getCenterXY()[0]);
      System.out.println("center's y is: " + c1.getCenterXY()[1]);

      // Test getArea() and getCircumference()
      System.out.printf("area is: %.2f%n", c1.getArea());
      System.out.printf("circumference is: %.2f%n", c1.getCircumference());

      // Test distance()
      System.out.printf("distance is: %.2f%n", c1.distance(c2));
      System.out.printf("distance is: %.2f%n", c2.distance(c1));
   }
}

1 Nhận xét

Đăng nhận xét

Mới hơn Cũ hơn