생성자는 인스턴스를 생성해주는 역할을 하는 특수한 메소드라고 할 수 있다. 그런데 반환 값이 있다면 엉뚱한 객체가 생성될 것이다. 따라서 반환 값을 필요로하는 작업에서는 생성자를 사용하지 않는다.
반환 값이 없기 때문에 return도 사용하지 않고, 반환 값을 메소드 정의에 포함시키지도 않는다.
자바에서 클래스의 이름과 동일한 메소드는 생성자로 사용하기로 약속되어 있다.
package test;
class Calculator{
int left, right;
public Calculator(int left, int right) {
this.left = left;
this.right = right;
}
public void sum()
{
System.out.println(this.left + this.right);
}
public void avg()
{
System.out.println((this.left + this.right) / 2);
}
}
public class Helloworld {
public static void main(String[] args)
{
Calculator c1 = new Calculator(10, 20);
c1.sum();
c1.avg();
Calculator c2 = new Calculator(20, 40);
c2.sum();
c2.avg();
}
}
6행의 클래스 명과 동일한 메소드 이것이 생성자이다.
26행 및 30행은 생성자를 이용해서 객체를 생성하는 방법을 보여준다.
상속(Ingeritance)이란 물려준다는 의미이다. 어떤 객체가 있을 때 그 객체의 필드(변수)와 메소드를 다른 객체가 물려 받을 수 있는 기능을 상속이라고 한다.
아래와 같은 경우에 속한다면 객체에 메소드를 추가하는 것이 어렵다.
package test;
class Calculator{
int left, right;
public void setOperands(int left, int right)
{
this.left = left;
this.right = right;
}
public void sum()
{
System.out.println(this.left + this.right);
}
public void avg()
{
System.out.println((this.left + this.right) / 2);
}
}
class Substraction extends Calculator
{
public void substraction()
{
System.out.println(this.left - this.right);
}
}
public class Helloworld {
public static void main(String[] args)
{
Substraction sub = new Substraction();
sub.setOperands(10, 20);
sub.sum();
sub.avg();
sub.substraction();
}
}
23행과 같이 extends
키워드로 Calculator 클래스를 상속 받는다.
부모 클래스와 자식 클래스의 관계를 상위(super) 클래스와 하위(sub) 클래스라고 표현하기도 한다.
또한 기초 클래스(base class), 유도 클래스(derived class)라고도 부른다.
상속한 클래스를 다시 상속하는 예제는 아래와 같다.
package test;
class Calculator{
int left, right;
public void setOperands(int left, int right)
{
this.left = left;
this.right = right;
}
public void sum()
{
System.out.println(this.left + this.right);
}
public void avg()
{
System.out.println((this.left + this.right) / 2);
}
}
class Substraction extends Calculator
{
public void substraction()
{
System.out.println(this.left - this.right);
}
}
class Multiplicationable extends Calculator
{
public void multiplicationable()
{
System.out.println(this.left * this.right);
}
}
class Divisionable extends Multiplicationable
{
public void divisionable()
{
System.out.println(this.left / this.right);
}
}
public class Helloworld {
public static void main(String[] args)
{
Substraction sub = new Substraction();
sub.setOperands(10, 20);
sub.sum();
sub.avg();
sub.substraction();
Divisionable div = new Divisionable();
div.setOperands(10, 20);
div.sum();
div.avg();
div.multiplicationable();
div.divisionable();
}
}
super는 상위 클래스를 가리키는 키워드다. 예제를 통해서 super의 사용법을 알아보자.
package test;
class Calculator{
int left, right;
public Calculator() {}
public Calculator(int left, int right) {
this.left = left;
this.right = right;
}
public void setOperands(int left, int right)
{
this.left = left;
this.right = right;
}
public void sum()
{
System.out.println(this.left + this.right);
}
public void avg()
{
System.out.println((this.left + this.right) / 2);
}
}
class Substraction extends Calculator
{
public Substraction(int left, int right) {
super (left, right);
}
public void substraction()
{
System.out.println(this.left - this.right);
}
}
class Multiplicationable extends Calculator
{
public void multiplicationable()
{
System.out.println(this.left * this.right);
}
}
class Divisionable extends Multiplicationable
{
public void divisionable()
{
System.out.println(this.left / this.right);
}
}
public class Helloworld {
public static void main(String[] args)
{
Substraction sub = new Substraction(10, 20);
sub.sum();
sub.avg();
sub.substraction();
Divisionable div = new Divisionable();
div.setOperands(10, 20);
div.sum();
div.avg();
div.multiplicationable();
div.divisionable();
}
}
super 키워드는 부모 클래스를 의미한다. 여기에 ()를 붙이면 부모 클래스의 생성자를 의미하게 된다.
이렇게 하면 부모 클래스의 기본 생성자가 없어져도 오류가 발생하지 않는다.
하위 클래스의 생성자에서 super를 사용할 때 주의할 점은 super가 가장 먼저 나타나야 한다는 점이다.
즉 부모가 초기화되기 전에 자식이 초기화 되는 일을 방지하기 위한 정책이라고 생각하자.
메소드 sum이 Substraction에 추가 되었다. 실행결과는 sub.sum이 상위 클래스의 메소드가 아니라 하위 클래스의 메소드 sum을 실행하고 있다는 것을 보여준다. 하위 클래스 입장에서 부모 클래스란 말하자면 기본적인 동작 방법을 정의한 것이라고 생각할 수 있다. 하위 클래스에서 상의 클래스와 동일한 메소드를 정의하면 부모 클래스로부터 물려 받은 기본 동작 방법을 변경하는 효과를 갖게 된다. 기본동작은 폭넓게 적용되고, 예외적인 동작은 더 높은 우선순위를 갖게하고 있다.
이것은 공학에서 일반적으로 발견되는 규칙이다. 이것을 메소드 오버라이딩(overriding)이라고 한다.
package test;
class Calculator{
int left, right;
public Calculator() {}
public Calculator(int left, int right) {
this.left = left;
this.right = right;
}
public void setOperands(int left, int right)
{
this.left = left;
this.right = right;
}
public void sum()
{
System.out.println(this.left + this.right);
}
public void avg()
{
System.out.println((this.left + this.right) / 2);
}
}
class Substraction extends Calculator
{
public Substraction(int left, int right) {
super (left, right);
}
public void sum() {
System.out.println("실행 결과는 " + (this.right + this.left) + "입니다.");
}
public void substraction()
{
System.out.println(this.left - this.right);
}
}
class Multiplicationable extends Calculator
{
public void multiplicationable()
{
System.out.println(this.left * this.right);
}
}
class Divisionable extends Multiplicationable
{
public void divisionable()
{
System.out.println(this.left / this.right);
}
}
public class Helloworld {
public static void main(String[] args)
{
Substraction sub = new Substraction(10, 20);
sub.sum();
}
}
실행 결과
실행 결과는 30입니다.
overriding을 하기 위해서는 메소드의 리턴 형식이 같아야 한다. 오버라이딩을 하기 위해서는 아래의 조건을 충족시켜야 한다.
위와 같이 메소드의 형태를 정의하는 사항들을 통틀어서 메소드의 서명(signature) 라고 한다.
이름은 같지만 시그니처는 다른 메소드를 중복으로 선언 할 수 있는 방법은 메소드 오버로딩(overloding) 이라고 한다.
package test;
class Calculator{
int left, right;
int third = 0;
public Calculator() {}
public Calculator(int left, int right) {
this.left = left;
this.right = right;
}
public void setOperands(int left, int right) {
this.left = left;
this.right = right;
}
public void setOperands(int left, int right, int third) {
this.setOperands(left, right);
this.third = third;
}
public void sum() {
System.out.println(this.left + this.right + this.third);
}
public void avg() {
System.out.println((this.left + this.right + this.third)/2);
}
}
class Substraction extends Calculator
{
public Substraction(int left, int right) {
super (left, right);
}
public void substraction()
{
System.out.println(this.left - this.right);
}
}
public class Helloworld {
public static void main(String[] args)
{
Substraction sub = new Substraction(10, 20);
sub.setOperands(10, 20);
sub.sum();
sub.avg();
sub.setOperands(10, 20, 30);
sub.sum();
sub.avg();
}
}
실행 결과
30
15
60
30
메소드 오버로딩은 매개변수를 사용한다. 즉 매개변수가 다르면 이름이 같아도 서로 다른 메소드가 되는 것이다.
반면에 매개변수는 같지만 리턴타입이 다르면 오류가 발생한다. 아래의 코드를 보자.
class OverloadingDemo {
void A() {
System.out.println("void A()");
}
void A(int arg1) {
System.out.println("void A(int arg1)");
}
void A(String arg1) {
System.out.println("void A(String arg1)");
}
/* Error Code */
/*int A() {
* System.out.println("int A()");
}*/
}
public class Helloworld {
public static void main(String[] args)
{
OverloadingDemo od = new OverloadingDemo();
od.A();
od.A(1);
od.A("Hello world");
}
}
void A()
void A(int arg1)
void A(String arg1)
더 많은 값을 대상으로 연산할 수 있는 계산기 코드는 아래와 같다.
package test;
class Calculator{
int[] operands;
public Calculator() {}
public void setOperands(int[] operands) {
this.operands = operands;
}
public void sum() {
int total = 0;
for(int value : this.operands) {
total += value;
}
System.out.println(total);
}
public void avg() {
int total = 0;
for(int value : this.operands) {
total += value;
}
System.out.println(total/this.operands.length);
}
}
public class Helloworld {
public static void main(String[] args)
{
Calculator ca = new Calculator();
ca.setOperands(new int[] {10, 20});
ca.sum();
ca.avg();
ca.setOperands(new int[] {10, 20, 30});
ca.sum();
ca.avg();
}
}
실행 결과
30
15
60
20
아래의 코드를 javac ClasspathDemo.java
를 통하여 컴파일 후 생성된 ClasspathDemo.class
및 Item.class
를 각각
D:\workspace\JAVA\LAB\ClasspathDemo.class
D:\workspace\JAVA\LAB\lib\Item.class
위와 같은 경로에 위치 시킨다고 가정한다.
class Item {
public void print() {
System.out.println("Hello world");
}
}
class ClasspathDemo {
public static void main(String[] args) {
Item t = new Item();
t.print();
}
}
위 코드를 실행시키는 콘솔 명령어는 아래와 같다.
java -classpath ".;lib" ClasspathDemo
리눅스, OSX 와 같은 유닉스 계열의 시스템이라면 아래와 같이 클론을 사용해야한다.
java -classpath ".:lib" ClasspathDemo
옵션 -classpath 는 자바를 실행할 때 사용할 클래스들의 위치를 가상머신에게 알려주는 역할을 한다.
.
현재 디렉터리에서 클래스를 찾는다는 뜻이다.
;
경로와 경로를 구분해주는 구분자
lib
현재 디렉터리에 없다면 현제 디렉터리의 하위 디렉터리 중 lib 에서 클래스를 찾는다는 의미다.
위 와 동일한 효과의 경로를 환경변수로 등록하는 방법은 아래와 같다.(windows only)
javac src/test/*.java -d bin
-d bin
은 컴파일된 결과를 bin 디렉토리 하위에 위치시킨다는 의미다.
자바 컴파일러는 자동으로 클래스의 패키지에 해당하는 디렉토리를 생성해준다.
package example3;
import example1.*;
import example2.*;
public class D {
public static void main(String[] args) {
example2.B b = new example2.B();
}
}
Package 명을 인스턴스 생성시에 명시해주면 명확한 B 에 대한 인스턴스를 생성할 수 있다.
각 구획 별 의미는 아래와 같다.
자바에서 제공하는 기본 패키지들은 아래와 같은 기능을 담고 있다.
자바 프로그래밍을 위한 가장 기본적인 패키지와 클래스를 포함하고 있다.
프로그램을 제어하기 위한 클래스와 데이터를 효율적으로 저장하기 위한 클래스들을 담고 있다.
키보드, 모니터, 프린터, 파일등을 제어할 수 있는 클래스들의 모음
통신을 위한 기능들을 담고 있다.
[JAVA] 접근제어자 (0) | 2018.06.12 |
---|---|
[JAVA] 기본 문법 (0) | 2018.05.31 |
[JAVA] 데이터 타입 (0) | 2018.05.28 |
[JAVA] 설치 및 실행 (0) | 2018.05.28 |