Example 8.2-1. Use of Class Members
package classmember; /** * 8.2-1 클래스 멤버의 사용 * @author DELL * */ public class Test { public static void main(String[] args) { ColoredPoint c = new ColoredPoint(); // error c.reset(); // error } } class Point { int x, y; private Point() { reset(); } Point(int x, int y) { this.x = x; this.y = y; } private void reset() { this.x = 0; this.y = 0; } } class ColoredPoint extends Point { int color; void clear() { reset(); // error } }
이 코드에는 4가지의 컴파일에러가 나타난다.
1. ColoredPoint 클래스에는 두개의 int 인자를 가진 생성자가 없다.
Point 클래스의 생성자를 상속하지 않았기 때문이다.
2. 선언한 생성자가 없기때문에, 기본생성자가 암묵적으로 생성이 되는데,
이 기본 생성자는 다음과 동일한 의미이다.
ColoredPoint() { super(); }
이것은 인자가 없는 생성자를 호출한다.
Point 클래스의 아무 인자도 없는 생성자는 private 생성자이며, 클래스 밖에서는 접근이 안된다.
나머지 둘의 에러는 reset메소드가 private이기 때문에 나타난다.
따라서 ColoredPoint 클래스에 상속이 되지 않는다.
ColoredPoint 안에서의 reset 호출과 main 메소드에서의 호출은 옳지 않다.
Example 8.2-2. Inheritance of Class Members with Package Access
다음과 같이 points 패키지에 존재하는 두 클래스를 살펴보자.
package points; public class Point { int x, y; public void move(int dx, int dy) { x += dx; y += dy; } }
package points; public class Point3d extends Point { int z; public void move(int dx, int dy, int dz) { x += dx; y += dy; z += dz; } }
그리고 다른 패키지의 세번째 클래스이다.
package anotherpoints; import points.Point3d; public class Point4d extends Point3d { int w; public void move(int dx, int dy, int dz, int dw) { x += dx; y += dy; z += dz; // compile-time errors w += dw; } }
points 패키지의 두 클래스는 컴파일 에러를 일으키지 않는다.
Point3d 클래스는 Point 클래스의 x와 y를 상속받는다.
같은 패키지이기 때문이다.
Point4d 클래스는 x와 y, 그리고 z를 상속받지 못한다.
다른패키지에 존재하기 때문이다.
다음 방법은 어떨까?
package anotherpoints; import points.Point3d; public class Point4d extends Point3d { int w; public void move(int dx, int dy, int dz, int dw) { super.move(dx, dy, dz); w += dw; } }
4d클래스의 부모클래스인 3d클래스의 move 메소드를 사용해 dx, dy, dz에 접근하였다.
위와 같이 작성하면, 컴파일에러가 안생긴다.
8.2-3. public과 protected 클래스 멤버의 상속
package points; public class Point { public int x, y; protected int useCount = 0; static protected int totalUseCount = 0; public void move(int dx, int dy) { x += dx; y += dy; useCount++; totalUseCount++; } }
위와 같은 클래스가 있을 때,
x와 y, useCount와 totalUseCount는 Point 클래스를 부모로 하는 모든 클래스에 상속이 가능하다.
따라서 다른 패키지라도 다음과 같이 컴파일이 정상진행이 된다.
package main; import points.Point; public class Test extends points.Point { public void moveBack(int dx, int dy) { x -= dx; y -= dy; useCount++; totalUseCount++; } }
8.2-4 private 클래스 멤버의 상속
class Point { int x, y; void move(int dx, int dy) { x += dx; y += dy; totalMoves++; } private static int totalMoves; void printMoves() { System.out.println(totalMoves); } } class Point3d extends Point { int z; void move(int dx, int dy, int dz) { super.move(dx, dy); z += dz; totalMoves++; // error } }
변수 totalMoves는 오직 Point 내부에서만 쓸 수 있다.
8.2-5. 접근할 수 없는 클래스의 멤버에 접근하기
Even though a class might not be declared public, instances of the class might be available
at run time to code outside the package in which it is declared by means of a public
superclass or superinterface.
An instance of the class can be assigned to a variable of such a
public type. An invocation of a public method of the object referred to by such a variable
may invoke a method of the class if it implements or overrides a method of the public
superclass or superinterface. (In this situation, the method is necessarily declared public,
even though it is declared in a class that is not public.)
package points; public class Point { public int x, y; public void move(int dx, int dy) { x += dx; y += dy; } }
package morePoints; public class OnePoint { public static points.Point getOne() { return new Point3ds(); } } class Point3ds extends points.Point { public int z; public void move(int dx, int dy, int dz) { super.move(dx, dy); z += dz; } public void move(int dx, int dy) { move(dx, dy, 0); } }
An invocation morePoints.OnePoint.getOne() in yet a third package would return
a Point3d that can be used as a Point, even though the type Point3d is not available
outside the package morePoints. The two-argument version of method move could then be
invoked for that object, which is permissible because method move of Point3d is public
(as it must be, for any method that overrides a public method must itself be public,
precisely so that situations such as this will work out correctly). The fields x and y of that
object could also be accessed from such a third package.
While the field z of class Point3d is public, it is not possible to access this field from code
outside the package morePoints, given only a reference to an instance of class Point3d
in a variable p of type Point. This is because the expression p.z is not correct, as p has
type Point and class Point has no field named z; also, the expression ((Point3d)p).z
is not correct, because the class type Point3d cannot be referred to outside package
morePoints.
출처 : jls 8
'자바' 카테고리의 다른 글
8.3 Field Declarations (2) (0) | 2021.10.11 |
---|---|
8.3 Field Declarations (1) (0) | 2021.10.11 |
람다 표현식과 this 키워드에 관하여 (0) | 2021.09.26 |
자바 Stream API (0) | 2021.09.25 |
[자바] 옵저버패턴 : java.util.Observer, Observable (0) | 2021.06.27 |