Difference between r1.5 and the current
@@ -1,16 +1,23 @@
[[TableOfContents]]
== 일시 ==
* 클래스 중첩 : 여러 클래스를 관리 할 때 클래스 안에 다시 클래스를 선언하여 중첩시키는 것.
{{{
Outer 객체1 = new Outer(); //Outer 클래스 객체 생성 방법
Outer.Inner 객체2 = 객체1.new Inner(); //Inner 클래스 객체 생성 방법
}}}
* 컴파일러를 돌리고 윈도우 탐색기를 이용하면 Outer$Inner.class 라는 파일도 있을 것이다. 이 파일이 바로 중첩된 클래스를 나타내는 것이다.
* static 메서드 내부에서는 일반 중첩 클래스의 객체가 선언 될 수 없다는 것
* 또 Inner 내부에 static과 관련된 멤버를 선언하는 것도 컴파일 에러를 발생시킨다
== 일시 ==
* 오후 12 : 10 ~ 오후 1 : 50
== 참가자 ==|| 유재범 || 참석 ||
|| 최다인 || 불참 ||
|| 이지수 || 참석 ||
|| 김용준 || 참석 ||
|| 김정민 || 참석 ||
== 진행 상황 == * [유재범] 학우의 발표
* JAVA의 정석 7-5~
=== 발표 내용 ==={{{
Outer 객체1 = new Outer(); //Outer 클래스 객체 생성 방법
Outer.Inner 객체2 = 객체1.new Inner(); //Inner 클래스 객체 생성 방법
}}}
* 컴파일러를 돌리고 윈도우 탐색기를 이용하면 Outer$Inner.class 라는 파일도 있을 것이다. 이 파일이 바로 중첩된 클래스를 나타내는 것이다.
* Inner 클래스에서는 Outer 클래스의 멤버를 이요할 수 있다. 하지만 Outer 클래스에서 Inner 클래스의 멤버를 이용하려면 객체를 직접 선언해야 한다.
* Inner 클래스에서는 Outer 클래스의 멤버를 이용할 수 있다. 하지만 Outer 클래스에서 Inner 클래스의 멤버를 이용하려면 객체를 직접 선언해야 한다.
* Outer 내부에서 Inner의 멤버를 사용하기 위해 객체를 선언하려면 현재 클래스의 객체를 대변하는 this가 있어야 한다.* static 메서드 내부에서는 일반 중첩 클래스의 객체가 선언 될 수 없다는 것
* 또 Inner 내부에 static과 관련된 멤버를 선언하는 것도 컴파일 에러를 발생시킨다
@@ -23,7 +30,7 @@
}
}
}}}
* Outer 클래스의 객체가 없어도 Inner 클래스의 객체를 만들 수 있다.
* 또한 static 멤버를 선언 할 수 있고 static 메서드도 만들어 사용 할 수 있다.
}
}}}
* 정적 중첩의 클래스는 static의 특성상 객체를 독립적으로 만들 수 있따.
* 정적 중첩의 클래스는 static의 특성상 객체를 독립적으로 만들 수 있다.
* Outer.Inner 객체 = new Outer.Inner();* Outer 클래스의 객체가 없어도 Inner 클래스의 객체를 만들 수 있다.
* 또한 static 멤버를 선언 할 수 있고 static 메서드도 만들어 사용 할 수 있다.
@@ -169,7 +176,7 @@
}
}}}
* 위와 같은 경우 에러가 발생한다. 에러를 발생하지 않게 하기 위해서는 B bp = (B)ap로 명시적으로 캐스팅을 해야 한다.
* 이항 연산자이며 피연산자는 참조형 변수와 타입, 연산 결과는 true, false이다.
* instanceof의 연산 결과가 true이면 해당 타입으로 형변환이 가능하다.
}}}
* 위와 같은 경우 에러가 발생한다. 에러를 발생하지 않게 하기 위해서는 B bp = (B)ap로 명시적으로 캐스팅을 해야 한다.
* 하지만 아직 문제는 있다. 만약 A ap = new A();라는 문맥이었다면 Exception in thread "main" java.lang.ClassCastException:A라는 런타임 에러가 발생한다. 이럴 때 instanceof라는 예약어가 참으로 유용하다.
* 하지만 아직 문제는 있다. 만약 A ap = new A();라는 문맥이었다면 Exception in thread "main" java.lang.ClassCastException:A라는 런타임 에러가 발생한다. 이럴 때 instanceof라는 예약어가 참으로 유용하다.
* instanceof 연산자 : 참조변수가 참조하는 인스턴스의 실제 타입을 체크하는데 사용* 이항 연산자이며 피연산자는 참조형 변수와 타입, 연산 결과는 true, false이다.
* instanceof의 연산 결과가 true이면 해당 타입으로 형변환이 가능하다.
@@ -189,23 +196,23 @@
}
}
}
* abstract(추상, 추상 메서드, 추상 클래스) : 부모클래스를 직접 사용하지 않고 자식을 통해서만 사용할 목적으로 혹은 단지 묶어 주기만 할 목적으로 클래스를 만들 때 추상 클래스를 사용한다.
* 접근_제한자 abstract class 클래스명 extends 상위_클래스 implements 상위_인터페이스{...}
* 추상 클래스는 일반 클래스의 모든 기능을 할 수 있다. 다만 그 자신의 객체만큼은 발생시키지 못한다.
* 추상 클래스는 일반 클래스의 멤버 이외에 추상 메서드를 가질 수 있다.
* 이런 이유는 다형성의 표현에서 오버라이딩이 되었음을 의미하는 것인데 이것은 반드시 오버라이딩이 되어야만 한다.
* 추상메서드를 만드는 이유는 상속받는 하위 클래스에게 디자인이 되어 있는 메서드를 재정의 하라고 명령을 내리기 위해서다.
* 추상클래스를 통해 인스턴스를 발생시키려고 하면 에러가 발생한다.
* 인터페이스 : 단일 상속의 제약을 보완하기 위해 자바에서 제안한 새로운 개념의 클래스. 이를 통하 자바는 다중 상속을 할 수 있게 되었다.
* 인터페이스의 정의
* 1. 다중 상속을 위한 클래스의 대안
}
}
}}]
}}}
* abstract(추상, 추상 메서드, 추상 클래스) : 부모클래스를 직접 사용하지 않고 자식을 통해서만 사용할 목적으로 혹은 단지 묶어 주기만 할 목적으로 클래스를 만들 때 추상 클래스를 사용한다.
* 접근_제한자 abstract class 클래스명 extends 상위_클래스 implements 상위_인터페이스{...}
* 추상 클래스는 일반 클래스의 모든 기능을 할 수 있다. 다만 그 자신의 객체만큼은 발생시키지 못한다.
* 이것은 주로 다형성을 표현할 목적으로 ㅁ낳이 사용하는데 이런 것을 "디자인 목적"이라고 한다. 쉽게 하나의 제품을 만들 때 참고하는 디자인 혹은 모델이라고 생각해두자.
* 이것은 주로 다형성을 표현할 목적으로 많이 사용하는데 이런 것을 "디자인 목적"이라고 한다. 쉽게 하나의 제품을 만들 때 참고하는 디자인 혹은 모델이라고 생각해두자.
* 만약 추상 클래스가 추상 메서드를 가지고 있다면 그것은 반드시 오버라이딩 되어야 한다.* 추상 클래스는 일반 클래스의 멤버 이외에 추상 메서드를 가질 수 있다.
* 접근_제한자 abstract 결과형_리턴값 메서드명(매개_변수들) throws 예외_클래스들;
* 접근_제한자 abstract 결과형_리턴값 메서드명(매개_변수들) throws 예외 클래스들;
* 여기서 중요한 것은 마지막에 세미클론으로 끝난다는 것이다. 즉, 내용부를 가지지 않고 이름만 있는 메서드이다.* 이런 이유는 다형성의 표현에서 오버라이딩이 되었음을 의미하는 것인데 이것은 반드시 오버라이딩이 되어야만 한다.
* 추상메서드를 만드는 이유는 상속받는 하위 클래스에게 디자인이 되어 있는 메서드를 재정의 하라고 명령을 내리기 위해서다.
* 추상클래스를 통해 인스턴스를 발생시키려고 하면 에러가 발생한다.
* 인터페이스 : 단일 상속의 제약을 보완하기 위해 자바에서 제안한 새로운 개념의 클래스. 이를 통하 자바는 다중 상속을 할 수 있게 되었다.
* 접근_제한자 interface 인터페이스 명 extends 상위_인터페이스{ 내용부}
* 접근_제한자 interface 인터페이스 명 extends 상위_인터페이스{ 내용부 }
attachment:IMG_20140721_034348.jpg
* 인터페이스는 다중 상속이 가능하다는 특징이 강하게 나타난다.* 인터페이스의 정의
* 1. 다중 상속을 위한 클래스의 대안
@@ -259,7 +266,7 @@
}
}
}}}
{{{
interface T3{
}
}}}
* 정적 중첩 클래스 : 인터페이스에 마지막으로 있을 수 있는 멤버는 정적 중첩 클래스오 ㅏ중첩 인터페이스이다. 클래스가 중첩 될 경우 무조건 public, static이기에 정적 중첩 클래스가 되는 것이다.
* 정적 중첩 클래스 : 인터페이스에 마지막으로 있을 수 있는 멤버는 정적 중첩 클래스와 중첩 인터페이스이다. 클래스가 중첩 될 경우 무조건 public, static이기에 정적 중첩 클래스가 되는 것이다.
* 따라서 외부에서 그 클래스에 대한 객체를 발생시킬 때에는 정적 중첩 클래스 객체 생성 방식을 따르게 된다.{{{
interface T3{
@@ -283,578 +290,336 @@
}
}}}
* int x 역시 public static final 이기 때문에 disp() 메서드에서 사용할 수 있는 것이다.
|| || abstract || 인터페이스 ||
|| 공통점 || 1. 디자인의 개념으로 다형성을 표현하기에 아주 적당한 형태이다.
2. 객체를 발생 시킬 수 없다.
3. 추상 메서드를 포함하고 있고, 그 메서드를 오버라이딩을 해야만 하위 클래스의 객체가 발생한다.
4. 표현의 방식에서 효율성을 고려하여 다형적인 표현을 주목적으로 한다.
|| 차이점 || 알아서 잘 생각하세요 ||
== 일시 ==
* 오후 12시 05분 ~ 1시 30분
== 참가자 ==
|| 유재범 || 참석 ||
|| 최다인 || 참석 ||
|| 이지수 || 참석 ||
|| 김용준 || 참석 ||
|| 김정민 || 참석 ||
== 진행 상황 ==
* 최다인 학우의 발표
* Java의 정석 - Chapter 6
=== 발표 내용 ===
* 객체지향 프로그래밍은 절차지향 프로그래밍의 반대개념이 아니다.
* 객체지향에도 절차지향의 개념이 포함되어 있음.
* Class는 일종의 설계도 개념, 설계도로 만들어 낸 제품을 객체, 또는 인스턴스라 함.
* 객체와 인스턴스의 차이
* 책상은 객체이다.
* 책상은 가구 클래스의 인스턴스이다.
* 실제로 생성한 객체 각각을 인스턴스라 부름.
* 객체의 구성
* 1. 속성 / 멤버변수 / 필드
* struct의 구성요소라고 봐도 무관
* 2. 기능 / 메서드 / 함수
* public과 private?
|| 분류 || 접근 지정자 || 클래스 내부 || 같은 패키지 내의 클래스 || 다른 모든 클래스 ||
|| 전용 멤버 || private || O || X || X ||
|| 패키지 멤버 || 없음 || O || O || X ||
|| 공용 멤버 || public || O || O || O ||
* 클래스 작성 -> 인스턴스 생성
* class 클래스명 { } (ex: class TV { ... })
* 클래스명 변수명; (ex: TV tv1;)
* 이 때 생성되는 변수는 인스턴스가 아니다. 생성하는 인스턴스의 주소값을 담을 수 있는 일종의 포인터 변수.
* 변수명 = new 클래스명(); (ex: tv1 = new TV();)
* new를 사용했을 때 인스턴스가 생성되며, 이 때의 주소값을 변수에 대입. 따라서 TV tv1 = new TV(); 처럼 한 문장에 쓸 수도 있다.
* 가비지 콜렉터
{{{
class TV {
...
}
TV tv1 = new TV();
TV tv2 = new TV();
//각각 별개인 두 개의 TV 인스턴스 생성
tv2 = tv1;
//tv2가 가리키는 인스턴스를 tv1이 가리키고있는 TV 인스턴스로 변경.
//이 때, 원래 tv2가 가리키고 있던 인스턴스는 사용하지 않는 상태가 되므로, JAVA의 가비지 콜렉터가 자동으로 메모리를 해제한다.
}}}
* 객체지향의 기본 개념 중 하나 : 구현의 세부 사항을 클래스 안에 감추어라.
* public 필드는 되도록 피해야한다.
* 필드에 직접 접근하는 방법보다는, 클래스에 메소드를 추가하여 필드에 대한 접근을 선별적으로 승인해야 한다.
* 필드와 관련된 두 종류의 메소드
* 접근자
* 보통 get을 메소드 이름 앞에 붙임
* 생성자
* 보통 set을 메소드 이름 앞에 붙임
* 장점
* 잘못된 값이 대입되는 것을 방지할 수 있다.
* 값이 바뀌면 안되는 필드의 경우, 생성자를 만들지 않음으로 자동적으로 읽기만 가능하게 할 수 있다.
{{{
//접근자 생성자 예시
class Car {
private String color;
public String getColor() {
return color;
} //접근자
public void setColor(String c) {
color = c;
} //생성자
}}}
* 기초형과 참조형
* 메소드의 매개변수가 기초형 변수일 경우, 값이 복사
* 참조형 변수일 경우에도 값이 복사되나, 그 값이 주소값이기 때문에 가리키는 객체의 값을 바꿀 수 있다.
* '''주의!''' 객체가 복사되는 것이 아니라는 것을 기억
* 이를 응용해, 배열이 참조형이라는 것을 이용하여 크기가 1짜리 배열을 만들어서 포인터처럼 쓸 수 있음...
* 가변 길이 인수
* 메소드로 전달된 인수의 정확한 개수를 알 수 없을 때 쓰임.
* 예제 (출처 : POWER JAVA 2판)
{{{
class Test {
void sub(int... v) {
System.out.println("인수의 개수 : " + v.length);
for (int x : v)
System.out.print(x + " ");
System.out.println();
}
}
public class VarArgsTest {
public static void main(String args[]) {
Test c = new Test();
c.sub(1);
c.sub(2, 3, 4, 5, 6);
c.sub();
}
}
/*
실행 결과
인수의 개수 : 1
1
인수의 개수 : 5
2 3 4 5 6
인수의 개수 : 0
*/
}}}
* static
* static으로 선언한 변수와 메소드는 '''클래스가 메모리에 올라갈 때''' 생성된다.
* 그 외의 것은 '''인스턴스 생성 시''' 함께 생성된다.
* static VarType VarName; -> 클래스 변수
* 클래스가 메모리에 올라갈 때 한 번 생성되므로, 나중에 몇 개의 인스턴스를 만들더라도 모든 인스턴스들이 한 가지 값을 공유하게 된다.
* static FuncType FuncName () {} -> 클래스 메서드
* 클래스가 메모리에 올라갈 때 생성되므로, 인스턴스를 생성하지 않더라도 사용할 수 있다.
* static으로 선언되지 않은 것들은 각각 인스턴스 변수, 인스턴스 메서드라고 불림.
* 얘네는 인스턴스를 생성해야 생성되기 때문에 인스턴스를 생성하지 않으면 사용 불가.
* 따라서, 클래스 메서드에서 인스턴스 변수를 사용할 경우 에러가 나게 된다.
* 클래스 메서드가 메모리에 올라갈 때, 인스턴스 변수는 선언되지 않은 상태이기 때문.
* 즉, 인스턴스들이 어떤 속성을 공유해야 할 필요성이 있을 때는 static 변수를 사용하고, 인스턴스를 생성하지 않고 사용하고 싶은 (예 : Math 클래스) 메서드는 static 메서드를 사용하자.
* 또한 메서드 안에서 인스턴스 변수를 사용하지 않는다면 static을 붙이는 것을 고려해보자.
* 선언이 한 번만 되기 때문에, 메모리를 아낄 수 있다? 속도가 빨라진다? 뭐였더라... 아무튼 이득.
* public static void main 을 생각하면 편함 ㅎㅎ
* 메서드 오버로딩
* 이름이 같고, 매개변수의 개수나 타입이 다른 메서드는 오버로딩된다. ('''메서드의 리턴타입은 관계가 없다!''')
{{{
//method overloading
public int square(int i) { return i*i; }
public double square(double i) { return i*i; }
}}}
* 장점 : 같은 기능을 하는 메소드들의 이름을 같게 지어, 번거로움을 줄일 수 있다.
* 생성자
* 객체를 생성하면, 객체의 데이터를 초기값으로 설정하는 작업을 한다.
* 이러한 작업을 위하여 생성자라는 특수한 메소드가 필요!
* 생성자는 일반 메소드와 흡사하나, 메소드 이름이 클래스 이름과 같고 반환값을 가지지 않으며, 반드시 public을 붙여야 한다.
* 한 클래스 안에 여러개의 생성자를 overloading 하는 것도 가능하다.
{{{
//예시
class Car {
private String color;
private int speed;
private int gear;
public Car(String c, int s, int g) {
color = c;
speed = s;
gear = g;
}
public Car() {
color = "red";
speed = 0;
gear = 1;
}
}
public class CarTest {
public static void main(String args[]) {
Car c1 = new Car("blue", 100, 0);
Car c2 = new Car();
}
}
}}}
* 클래스 내에 생성자를 적지 않는 경우, 자동적으로 default 생성자가 만들어짐.
* default 생성자는 비어있음.
* public car () { }
* '''주의!''' 생성자가 하나라도 있다면, 디폴트 생성자는 만들어지지 않는다.
* 따라서 위의 예시에서 public Car() { ... } 생성자를 삭제할 경우, Car c2 = new Car(); 부에서 오류가 나게 된다.
* 생성자에서 다른 생성자를 호출하기
* 생성자는 비슷한 초기화 작업을 수행하기 때문에 하나의 생성자에서 다른 생성자를 호출하는 경우가 많음
* 기존의 생성자를 호출할 때는 this() 라는 예약어를 사용한다.
* '''주의!''' 다른 생성자를 호출하는 문장은 생성자의 맨 첫 번째 문장이어야 한다!
{{{
class Car {
private String color;
private int speed;
private int gear;
public Car(String c, int s, int g) {
color = c;
speed = s;
gear = g;
}
public Car(String c) {
this(c, 0, 1);
}
}
}}}
* this 참조
* 모든 객체는 키워드 this를 사용하여 자기 자신을 참조할 수 있다.
* 필드의 이름과 메소드 매개변수의 이름이 동일한 경우, 구분하기 위하여 사용
{{{
public void setSpeed(int speed)
{
this.speed = speed; //speed는 매개변수, this.speed는 필드
}
}}}
* 메소드 몸체에서 필드나 메소드를 좀 더 확실하게 하려고 할 때 사용
{{{
public Time(int h, int m, int s) {
this.setTime(h, m, s); //this는 없어도 된다.
}
}}}
* 메소드 매개변수로 자기 자신에 대한 참조를 넘겨야할 필요가 있는 경우에 사용
{{{
System.out.println(this);
}}}
* ~~왜 클래스 이름을 안쓰고 this라고 하나요?~~
* ~~재범이 밥먹어쪄요라고 안하잖아요~~
== 다음 진행 ==
=== 유재범 ===
과제 1
package hanjagonghomework;
import java.io.*;
public class Product {
BufferedReader in;
int price;
String name = "";
public Product(){
this.in = new BufferedReader(new InputStreamReader(System.in));
price = 10000;
name = "SAMSUNG";
}
public Product(int price, String name){
this.price = price;
this.name = name;
}
public Product(int price){
this.price = price;
}
public Product(String name){
this.name = name;
}
public String getName(){
return name;
}
public int getPrice(){
return price;
}
public void setName(String name){
this.name = name;
}
public void setPrice(int price){
this.price=price;
}
public void Print(){
System.out.println("이름 : " + name);
System.out.println("가격 : " + price);
}
}
}}}
과제 2
{{{
package hanjagonghomework;
import java.io.*;
public class MP3 {
BufferedReader in;
String company;
int size;
public MP3(String company, int size){
this.company = company;
this.size = size;
}
public MP3(String company){
this.company = company;
}
public MP3(){
this.in = new BufferedReader(new InputStreamReader(System.in));
this.company = "I-Pot";
this.size = 2;
}
public String getCompany(){
return company;
}
public int getSize(){
return size;
}
public void setCompany(String company){
this.company = company;
}
public void setSize(int size){
this.size = size;
}
public void Print(){
System.out.println("회사 : " + company);
System.out.println("용량 : " + size + "Gb");
}
}
출력 클래스
package hanjagonghomework;
import java.io.*;
public class Homework0714 {
System.out.println("Product");
Product rd = new Product(5000, "LG");
rd.Print();
rd.setPrice(1000);
rd.getPrice();
rd.setName("삼성");
rd.getName();
rd.Print();
System.out.println("MP3");
MP3 af = new MP3();
af.Print();
af.setCompany("아이리버");
af.setSize(6);
af.getCompany();
af.getSize();
af.Print();
}
}}}
=== 최다인 ===
=== 이지수 ===
과제 1
public static void main(String[] ar){
Product obj1 = new Product();
Product obj2 = new Product(1000);
Product obj3 = new Product("cheetose");
Product obj4 = new Product("diagestive", 1500);
obj1.setPrice(500);
obj1.setName("eggmong");
System.out.println(obj1.getName() + obj1.getPrice());
obj2.setName("pepero");
System.out.println(obj2.getName() + obj2.getPrice());
obj3.setPrice(1500);
System.out.println(obj3.getName() + obj3.getPrice());
System.out.println(obj4.getName() + obj4.getPrice());
}
String name;
int price;
public Product(String name, int price){
this.name = name;
this.price = price;
}
public Product(String name){
this.name = name;
}
public Product(int price){
this.price = price;
}
public Product(){
}
String getName(){
return this.name;
}
int getPrice(){
return this.price;
}
void setName(String name){
this.name = name;
void setPrice(int price){
this.price = price;
}
}
}}}
과제 2
{{{
public class MP3test{
public static void main(String[] ar){
MP3 obj1 = new MP3();
MP3 obj2 = new MP3("LG");
MP3 obj3 = new MP3("samsung", "50GB");
obj2.setSize("7GB");
System.out.println(obj2.company + " " + obj2.getSize());
System.out.println(obj3.company + " " + obj3.size);
}
class MP3{
String company;
String size;
public MP3(String company, String size){
this.company = company;
this.size = size;
}
public MP3(String company){
this.company = company;
}
public MP3(){
company = "아이팟";
size = "2GB";
}
String getCompany(){
return company;
}
String getSize(){
return size;
}
void setCompany(String company){
this.company = company;
}
void setSize(String size){
this.size = size;
}
}}}
* 과제 1
package test04;
public class ProductTest {
public static void main(String[] args) {
}
class Product{
private String name;
private int price;
public Product(String name, int price){
this.name = name;
this.price = price;
}
public Product(String name){
this.name = name;
}
public Product(int price){
this.price = price;
}
public Product(){}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getPrice(){
return price;
}
public void setPrice(int price){
this.price = price;
}
}
}}}
* 과제 2
{{{
package test04;
public class MP3test {
public static void main(String[] args) {
}
}
class MP3{
private String company = "아이팟";
private int size = 2048;//2G
public MP3(String company, String size){
this.company = company;
this.size = Integer.valueOf(size);
}
public MP3(String company){
this.company = company;
}
public MP3(){}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public void pirnt(){
System.out.println("company : "+this.company);
System.out.println("size : "+this.size);
}
}
}}}
----
=== 김정민 ===
== 후기 ==
* 내가 대략 정리해서 써놓을게 ㅡㅡㅋ -[최다인]
* get,set을 Source -> Generate Getters and Setters...를 사용하면 자동으로 만들 수 있습니당. - [김용준]
* 그리고 슬슬 과제페이지를 따로 만들어서 들어가서 보도록 만들어야할꺼 같아요. - [김용준]
* 나중에 날 잡아서 git 사용법을 다시 알아보도록 할까요? 데블스때 들은게 슬슬 산화해가는 느낌이.. - [유재범]
* 생성자 자동 생성 Source -> Generate Constructor using Fields - [김용준]
* 저희 과제 출력 클래스도 만들어야 하는건가요? - [유재범]
* 다인 선배님 강의에 중첩 클래스에 대한 내용은 없는 것 같은데 혹시 다른 사람들 책에 중첩 클래스 내용이 없나요? - [유재범]
-----
[한자공/시즌3]
== 다음 진행 ==
== 과제 ==
=== 유재범 ===
}}}
* int x 역시 public static final 이기 때문에 disp() 메서드에서 사용할 수 있는 것이다.
* abstract와 인터페이스
* 공통점
* 1. 디자인의 개념으로 다형성을 표현하기에 아주 적당한 형태이다.
* 2. 객체를 발생 시킬 수 없다.
* 3. 추상 메서드를 포함하고 있고, 그 메서드를 오버라이딩을 해야만 하위 클래스의 객체가 발생한다.
* 4. 표현의 방식에서 효율성을 고려하여 다형적인 표현을 주목적으로 한다.
* 차이점
*
* 만약 단지 하위클래스들을 통합 관리하기 위한 목적만 있고 상위 클래스로서 아무런 역할도 할 필요 없다면 abstract보다는 인터페이스가 더 효율적이다. * Chapter 7
* 객체지향 프로그래밍 2
* 발표 : [김용준]
* 이지수
* 8단원 예외처리
* 24일은 그린팩토리~~(그으리인팩토으리)~~ 견학으로 스터디를 쉬고 28일날 진행합니다.
== 과제 == * [https://www.google.co.kr/url?sa=t&source=web&rct=j&ei=rtHFU7XxMMXk8AXSq4LwCQ&url=http://fortune94.tistory.com/attachment/cfile10.uf%40223FCA45524E568F2C46C1.pdf&cd=3&ved=0CCYQFjAC&usg=AFQjCNFN4ldn4rztksHRCooww_mF_0vzaA&sig2=si4JLRUgqS_1qN0Ca_mk5Q 다운로드 링크] 과제 2번까지.
* 그 동안 배운 개념(상속, 다형성 등)을 활용해서 도서 관리 프로그램 만들기
* 적어도 지정한 기능을 구현해서 프로그램이 동작하도록 하게 하면 된다.
* 조건
* 도서관리 클래스를 다형성을 통해서 코딩하기
* 상속 이용할 것
{{{ 도서관리 프로그램_v1.0
========= 데이터 구조 =========
회원 - 이름
- 생년월일
- 전화번호
- 대출내역
도서 - 제목
- 저자
- 출판사
- 고유코드
- 현재 비치수
========= 구현해 기능 =========
회원 - 등록
- 수정
- 도서 대출 가능 확인(대출제한 건수, 기한, 연속 대출)
- 탈퇴
도서 - 대출
- 반납
- 책 상태 (대출가능 여부)
- 책 정보 확인
}}}=== 유재범 ===
{{{package hanjagonghomework;
import hanjagonghomework.Active.Book2;
import hanjagonghomework.Active.Member2;
public static void main(String []ar) throws IOException{
interface Active{
public class Member implements Active{
public Member(){};
int arrcount = 0;
String name = "유재범";
String birth = "1995년 12월 17일";
String phnum = "01068267677";
public String saveMemberData[][] = {{name, birth, phnum}};
public int rentcount = 0;
}{{{
public class ProductTest{
public class Member2 extends Member implements Active{
private static BufferedReader in;
static{
in = new BufferedReader(new InputStreamReader(System.in));
}
Member2(){};
public void getname(String name) throws IOException{
System.out.print("이름을 입력해 주십시오 : ");
name = in.readLine();
saveMemberData[arrcount][0] = name;
}
public void getbirth(String birth) throws IOException{
int year = 0;
int month = 0;
int date = 0;
boolean booly = false;
do{
booly = false;
try{
System.out.print("태어난 연도는? ");
year = Integer.parseInt(in.readLine());
}catch(NumberFormatException nfe){
System.out.println("잘못된 연도입니다.");
booly = true;
}
}while(booly);
do{
booly = false;
try{
System.out.print("태어난 달은? ");
month = Integer.parseInt(in.readLine());
}catch(NumberFormatException nfe){
System.out.println("잘못된 달입니다.");
booly = true;
}
}while(booly);
do{
booly = false;
try{
System.out.print("태어난 날짜는? ");
date = Integer.parseInt(in.readLine());
}catch(NumberFormatException nfe){
System.out.println("잘못된 날짜입니다.");
booly = true;
}
}while(booly);
birth = year + "년 " + month + "월 " + date + "일";
saveMemberData[arrcount][1] = birth;
}
public void getphnum(String phnum) throws IOException{
System.out.print("전화번호를 입력해주세요 : ");
phnum = in.readLine();
saveMemberData[arrcount][2] = phnum;
}
public String setname(){
return name;
}
public String setbirth(){
return birth;
}
public String setphnum(){
return phnum;
}
public void Addmem() throws IOException{
Member2 admem = new Member2();
arrcount++;
admem.getname(name);
admem.getbirth(birth);
admem.getphnum(phnum);
}
public void Watchmem(){
for(int pp=0; pp<arrcount; pp++){
System.out.println("회원 이름 : " + saveMemberData[pp][0]);
System.out.println("생년월일 : " + saveMemberData[pp][1]);
System.out.println("핸드폰번호 : " + saveMemberData[pp][2]);
System.out.println();
System.out.println();
}
}
}class Product{
public class Book implements Active{
String book = "푸른 지붕의 앤";
String writer = "Lucy Maud Montgomery";
String bocom = "NEXUS";
public String [][] saveBookData = {{"푸른 지붕의 앤", "Lucy Maud Montgomery", "NEXUS", "", ""}};
public int bookarrcount = 0;
int bocode = 1234;
int bocount = 2;
int rentcode = 0;
} public class Book2 extends Book implements Active{
private static BufferedReader in;
static{
in = new BufferedReader(new InputStreamReader(System.in));
}
Book2(){};
int count=0;
public void getbook(String book) throws IOException{
System.out.print("책 이름을 등록해주세요 : ");
book = in.readLine();
saveBookData[bookarrcount][0] = book;
}
System.out.println(obj1.company + " " + obj1.size);
public void getwriter(String writer) throws IOException{
System.out.print("저자를 등록해주세요 : ");
writer = in.readLine();
saveBookData[bookarrcount][1] = writer;
}
public void getbocom(String bocom) throws IOException{
System.out.print("출판사를 등록해주세요 : ");
bocom = in.readLine();
saveBookData[bookarrcount][2] = bocom;
}
}
public String setbook(){
return book;
}
public String setwriter(){
return writer;
}
public String setbocom(){
return bocom;
}
public int setbocode(){
return (bocode+count);
}
public int setbocount(){
return bocount;
}
public void bookRent(){
if(bocount <= 0){
System.out.println("책을 대여하실 수 없으십니다.");
}
else{
bocount--;
rentcode ++;
}
}
public void bookReturn(){
if(bocount >= 2){
System.out.println("반납하실 책이 없읏비니다.");
}
else{
rentcode --;
bocount++;
}
}
public void WatchBookInfo() throws IOException{
Book2 watbok = new Book2();
watbok.getwriter(writer);
watbok.getbook(book);
watbok.getbocom(bocom);
count++;
}
public void setBookInfo(){
System.out.println("책 제목 : " + book);
System.out.println("저자 : " + writer);
System.out.println("출판사 : " + bocom);
System.out.println("고유 코드 : " + bocode+count);
System.out.println("잔여 도서량 : " + bocount);
}
}}
=== 김용준 ===
{{{
public class Library {
public static void main(String[] args) throws IOException{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
Member2 memmenu = new Member2();
Book2 bookmenu = new Book2();
while(true){
boolean boolmenu = false;
int menunum = 0;
System.out.print("무엇을 하시겠습니까?"
+ "(1.회원증 생성 "
+ "2.회원 정보 확인 "
+ "3.책 정보 입력 "
+ "4.책 정보 확인 "
+ "5.책 대여 "
+ "6.책 반납) : ");
do{
boolmenu = false;
}while(boolmenu);
try{
menunum = Integer.parseInt(in.readLine());
if(menunum > 6 || menunum <= 0){
System.out.println("잘못된 숫자입니다.");
boolmenu = true;
}
}catch(NumberFormatException nfe){
System.out.println("잘못된 숫자입니다.");
boolmenu = true;
}
if(menunum == 1){
memmenu.Addmem();
continue;
}
else if(menunum == 2){
memmenu.Watchmem();
continue;
}
else if(menunum == 3){
bookmenu.WatchBookInfo();
continue;
}
else if(menunum == 4){
bookmenu.setBookInfo();
continue;
}
}
else if(menunum == 5){
bookmenu.bookRent();
continue;
}
else if(menunum == 6){
bookmenu.bookReturn();
continue;
}
}
}
}}}
* 반복을 넣긴 했는데 책을 등록할 때, 회원 등록 할 때 그걸 저장해서 나중에 불러오고 싶었으나 어떻게 할 줄 몰라 실패
* 회원 정보나 책 정보를 넣으면 들어가기는 하는데 나중에 뽑을 때 초기 값으로 나온다. 왜이러지?
* 기타 필요 없거나 하나로 통일 될 수 있는 기능은 통일했습니다. 쓸데없이 여러가지 같은거 넣을 필요는 없을거 같았습니다.
* 생각해보니 다형성 쓸 필요가 없었습니다.
* 인터페이스를 main 클래스에서 받아서 쓰려니까 오류가 났는데 질문을 할 수도 없고 해서 그냥 import로 받았는데 이거 왜이러는지 아시는분 답변좀요.
* 하면 재밌는데 하기 전에 진짜 죽어도 하기 싫어서 큰일 날뻔했습니다.
* 다른 사람은 몰라도 김용준 과제 안하면 간식 사와라...
* 위키를 한번 쓰다 날려 내용을 도저히 못쓰겠습니다 - [유재범]
* 고쳐왔는데 결국 저장이 되도 계속 날라가네... 이 이상을 다른 선배님들께 물어봐도 내 코드가 잘못됬다는데 누구 코드좀 봐줄 사람 없으신가?
=== 최다인 ==={{{
}}}
=== 이지수 ==={{{
}}}
=== 김용준 ==={{{
}}}
=== 김정민 ==={{{
}}}
== 후기 == * 주말에 과제만 하면 되겠군... - [유재범]
* 금요일날 일찍 고향에 내려와야 되서 불참합니다. - [김용준]
* 이번주 목요일은 그린팩토리로 없을거고 다음주 월요일이 불참인건가? - [유재범]
* 아 금요일날 안하는구나. 착각함 ㅋㅋㅋㅋ - [김용준]
----
[한자공/시즌3]
3.1. 발표 내용 ¶
- 클래스 중첩 : 여러 클래스를 관리 할 때 클래스 안에 다시 클래스를 선언하여 중첩시키는 것.
Outer 객체1 = new Outer(); //Outer 클래스 객체 생성 방법 Outer.Inner 객체2 = 객체1.new Inner(); //Inner 클래스 객체 생성 방법
- 컴파일러를 돌리고 윈도우 탐색기를 이용하면 Outer$Inner.class 라는 파일도 있을 것이다. 이 파일이 바로 중첩된 클래스를 나타내는 것이다.
- Inner 클래스에서는 Outer 클래스의 멤버를 이용할 수 있다. 하지만 Outer 클래스에서 Inner 클래스의 멤버를 이용하려면 객체를 직접 선언해야 한다.
- Outer 내부에서 Inner의 멤버를 사용하기 위해 객체를 선언하려면 현재 클래스의 객체를 대변하는 this가 있어야 한다.
- static 메서드 내부에서는 일반 중첩 클래스의 객체가 선언 될 수 없다는 것
- 또 Inner 내부에 static과 관련된 멤버를 선언하는 것도 컴파일 에러를 발생시킨다
- static 메서드 내부에서는 일반 중첩 클래스의 객체가 선언 될 수 없다는 것
- Outer 내부에서 Inner의 멤버를 사용하기 위해 객체를 선언하려면 현재 클래스의 객체를 대변하는 this가 있어야 한다.
- 정적 중첩 클래스 : 중첩 클래스 내부에서 static과 관련된 멤버를 선언할 수 있는 클래스
- 일반 중첩 클래스 내부에는 static과 관련된 멤버를 선언할 수 없다. 그러나 Outer 클래스의 멤버를 단지 이용만 할 때에는 static이든 아니든 관계 없이 이용 할 수 있다.
- 일반 중첩 클래스 내부에는 static과 관련된 멤버를 선언할 수 없다. 그러나 Outer 클래스의 멤버를 단지 이용만 할 때에는 static이든 아니든 관계 없이 이용 할 수 있다.
class Outer{ static class Inner{ .......... } }
- 정적 중첩의 클래스는 static의 특성상 객체를 독립적으로 만들 수 있다.
- Outer.Inner 객체 = new Outer.Inner();
- Outer.Inner 객체 = new Outer.Inner();
- Outer 클래스의 객체가 없어도 Inner 클래스의 객체를 만들 수 있다.
- 또한 static 멤버를 선언 할 수 있고 static 메서드도 만들어 사용 할 수 있다.
- 그래서 Inner 클래스 내부에 static을 선언하여 사용하고 싶다면 정적 중첩 클래스를 사용해야 한다. 객체 선언 방식은 위와 같은 방식으로만 발생시킬 수 있따.
- Outer 클래스의 멤버는 static일 경우에만 사용할 수 있다. 이것은 마치 일반 멤버를 static 메서드 내부에서 사용할 수 없는것과 유사하다
- 그래서 Inner 클래스 내부에 static을 선언하여 사용하고 싶다면 정적 중첩 클래스를 사용해야 한다. 객체 선언 방식은 위와 같은 방식으로만 발생시킬 수 있따.
public class Round12_Ex04 { public static class Inner3{ public static void main(String[] ar){ System.out.println("Inner 클래스 내부의 main 메서드"); } } }
- 위와 같은 경우 java Round12_Ex04로 실행하면 main() 메서드가 Inner 클래스 내부에 있기 때문에 찾을 수 없어 JVM이 main()을 찾을 수 없다는 에러가 뜬다. 그래서 실행 시킬때에는 java Round12_Ex04$Inner3으로 실행을 해야 한다.
- 이것은 실제 메서드가 있는 곳을 지칭하는 것이다.
- 이것은 실제 메서드가 있는 곳을 지칭하는 것이다.
- 지역 중첩 클래스 : 특정 메서드에 한정적인 용도로 사용할 클래스로 등장
- 일반적으로 보통 클래스와 동일하나 접근 제한자와 지정 예약어를 사용할 수 없다는 형태이다.
- 만일 일반 중첩 클래스처럼 main() 메서드의 멤버를 사용하려면 그 멤버는 반드시 final로 선언되어 있어야만 한다.
- 컴파일을 하면 Round12_Ex06.class 외에 Round12_Ex06$1Inner5.class라는 클래스가 생성된다.
- 일반 중첩 클래스와 유사하가 static 멤버를 선언하지 못한다.
- 일반적으로 보통 클래스와 동일하나 접근 제한자와 지정 예약어를 사용할 수 없다는 형태이다.
- 익명 중첩 클래스 : class라는 예약어와 클래스 명을 가지지 않고 단지 instance의 생성과 내용부의 정의만 가지고 있는 클래스
- 지역 중첩 클래스의 변형된 형태
- 다만 여기에 사용되는 중첩 클래스는 이미 기존에 존재 하는 것이어야 한다.
- 또한 이 내에서 사용 할 수 있는 외부 데이터도 final로 선언되어 있어야 한다.
- 내용부가 서로 다른 특정 메서드의 실행을 주관 하기 위해서 사용
- 접근 제한자의 사용에 주의해야 한다. 자기 자신의 멤버일지라도 정의되는 영역이 다르기 때문이다.
- 접근 제한자의 사용에 주의해야 한다. 자기 자신의 멤버일지라도 정의되는 영역이 다르기 때문이다.
- 지역 중첩 클래스의 변형된 형태
class Inner6{ int y = 200; public Inner6(){ this.disp(); } public void disp(){} } public class Round12_Ex07 { public static void main(String[] ar){ final int x = 100; new Inner6(){ public void disp(){ System.out.println("Default 생성자"); System.out.println("x = " + x); System.out.println("y = " + y); } }; } }
- 위 예시를 컴파일 후 탐색기로 클래스 파일을 찾아보면 Inner6.class, Round12_Ex07.class, Round12_Ex07$1.class. 이렇게 3개가 생성이 된다.
- 이 중 마지막이 익명 중첩 클래스인다 이름에서 알 수 있듯이 익명이기에 숫자로 그 클래스를 표시한다.
- 만약 main() 메서드 내부에 다른 익명 중첩 클래스가 있다면 이 클래스는 Round12_Ex07$2.class가 될 것이다.
- 이 중 마지막이 익명 중첩 클래스인다 이름에서 알 수 있듯이 익명이기에 숫자로 그 클래스를 표시한다.
- 익명 중첩 클래스는 내부에 생성자를 작성할 수 없다.
- 만약 작성하면 invalid 메서드 declaration 이렇게 뜰 것이다.
- 만약 작성하면 invalid 메서드 declaration 이렇게 뜰 것이다.
- 다형성 : 여러개의 개별적 클래스를 하나의 부모 클래스 객체로 통합하여 관리하여 그 효율성을 높인 것
- 예 : 배열
- 다형성의 표현
- 예 : 배열
A ap = new A(); A bp = new B(); A cp = new C();
- 여기서 중요한 것은 자신의 클래스 객체가 아니지만 자신의 부모 클래스라면 인스턴스를 부모 객체에 담을 수 있다는 것이다.
class A3{ public String toString(){ return "A3 클래스"; } } class B3{ public String toString(){ return "B3 클래스"; } } public class Round13_Ex01 { public static void main(String[] ar){ A3 ap = new A3(); B3 bp = new B3(); System.out.println("ap = " + ap); System.out.println("bp = " + bp); } }
- 위 클래스 A3, B3는 언뜻 보면 연관이 되어 있지 않지만 사실 다형적인 표현을 사용할 수 있다.
- 왜냐하면 모두 Object를 부모로 두기 때문이다. 그래서 이를 아래와 같이 사용 할 수도 있다.
- 왜냐하면 모두 Object를 부모로 두기 때문이다. 그래서 이를 아래와 같이 사용 할 수도 있다.
public class Round13_Ex01 { public static void main(String[] ar){ Object[] obj = new Object[2]; obj[0] = new A3(); obj[1] = new B3(); for(int a = 0; a<obj.length; a++){ System.out.println("abj[" + a + "] = " + obj[a]); } } }
- 다형적인 표현에서 멤버에 대한 접근 규정
- 부모 클래스가 가지고 있는 모든 멤버들에 접근할 수 있다.
- 단, 자식 클래스에서 메서드 오버라이딩을 했다면 오버라이딩이 된 자식의 멤버에 접근이 된다.
- 단, 자식 클래스에서 메서드 오버라이딩을 했다면 오버라이딩이 된 자식의 멤버에 접근이 된다.
- 멤버 필드의 경우 부모 클래스의 멤버 필드에만 접근 할 수 있다.
- 자식 클래스의 멤버 필드는 오버라이딩이 된 자식 클래스의 메서드에 의해서만 접근 할 수 있다.
- 자식 클래스의 멤버 필드는 오버라이딩이 된 자식 클래스의 메서드에 의해서만 접근 할 수 있다.
- 부모 클래스가 가지고 있는 모든 멤버들에 접근할 수 있다.
- 다형성에서 멤버 필드로의 접근
- 필드는 다형성으로 표현 되었을 때는 객체를 통해 부모 클래스의 멤버 필드에만 접근 할 수 있다.
- 상위 하위 모두 동일한 이름의 필드라 하더라도 상위 클래스의 멤버 필드의 것만 접근 할 수 있다.
- 필드는 다형성으로 표현 되었을 때는 객체를 통해 부모 클래스의 멤버 필드에만 접근 할 수 있다.
- 다형성에서 메서드로의 접근
- 우선은 상위 클래스의 메서드에 접근 할 수 있고 하위 클래스의 메서드에는 접근 할 수 없다.
- 하지만 상위와 하위에 동시에 있는 오버라이딩이 된 메서드에 대해서는 하위의 멤버를 실행 할 수 있다.
- 우선은 상위 클래스의 메서드에 접근 할 수 있고 하위 클래스의 메서드에는 접근 할 수 없다.
class A6{ public void aaa(){ System.out.println("aaa"); } public void bbb(){ System.out.println("bbb"); } } class B6 extends A6{ public void bbb(){ System.out.println("bbb1"); } public void ccc(){ System.out.println("ccc"); } } public class Round13_Ex11 { public static void main(String[] ar){ A6 ap = new B6(); ap.aaa();//상위 클래스의 메서드에 접근 ap.bbb();//오버라이딩 된 하위 클래스에 접근 //ap.ccc();//하위 클래스의 메서드에 접근 } }
- 다형성은 어떤 값이 올지 예상을 하면 어렵지 않다고 한다.
class A{ ...} class B extends A{...} public class C{ public static void main(String[]ar){ A ap = new B(); B bp = ap; } }
- 위와 같은 경우 에러가 발생한다. 에러를 발생하지 않게 하기 위해서는 B bp = (B)ap로 명시적으로 캐스팅을 해야 한다.
- 하지만 아직 문제는 있다. 만약 A ap = new A();라는 문맥이었다면 Exception in thread "main" java.lang.ClassCastException:A라는런타임 에러가 발생한다. 이럴 때 instanceof라는 예약어가 참으로 유용하다.
- instanceof 연산자 : 참조변수가 참조하는 인스턴스의 실제 타입을 체크하는데 사용
- 이항 연산자이며 피연산자는 참조형 변수와 타입, 연산 결과는 true, false이다.
- instanceof의 연산 결과가 true이면 해당 타입으로 형변환이 가능하다.
- 이항 연산자이며 피연산자는 참조형 변수와 타입, 연산 결과는 true, false이다.
- instanceof 연산자 : 참조변수가 참조하는 인스턴스의 실제 타입을 체크하는데 사용
class A{} class B extends A{} public class Test{ public static void main(String[] ar){ A ap = new B(); B bp = null; if(ap instanceof B){//형식 : 객체 instanceof 변환할 클래스 bp = (B)ap; System.out.println("형 변환이 가능하다."); } else{ System.out.println("형 변환이 불가능 하다"); } } }
- abstract(추상, 추상 메서드, 추상 클래스) : 부모클래스를 직접 사용하지 않고 자식을 통해서만 사용할 목적으로 혹은 단지 묶어 주기만 할 목적으로 클래스를 만들 때 추상 클래스를 사용한다.
- 접근_제한자 abstract class 클래스명 extends 상위_클래스 implements 상위_인터페이스{...}
- 추상 클래스는 일반 클래스의 모든 기능을 할 수 있다. 다만 그 자신의 객체만큼은 발생시키지 못한다.
- 이것은 주로 다형성을 표현할 목적으로 많이 사용하는데 이런 것을 "디자인 목적"이라고 한다. 쉽게 하나의 제품을 만들 때 참고하는 디자인 혹은 모델이라고 생각해두자.
- 만약 추상 클래스가 추상 메서드를 가지고 있다면 그것은 반드시 오버라이딩 되어야 한다.
- 이것은 주로 다형성을 표현할 목적으로 많이 사용하는데 이런 것을 "디자인 목적"이라고 한다. 쉽게 하나의 제품을 만들 때 참고하는 디자인 혹은 모델이라고 생각해두자.
- 추상 클래스는 일반 클래스의 멤버 이외에 추상 메서드를 가질 수 있다.
- 접근_제한자 abstract 결과형_리턴값 메서드명(매개_변수들) throws 예외 클래스들;
- 여기서 중요한 것은 마지막에 세미클론으로 끝난다는 것이다. 즉, 내용부를 가지지 않고 이름만 있는 메서드이다.
- 이런 이유는 다형성의 표현에서 오버라이딩이 되었음을 의미하는 것인데 이것은 반드시 오버라이딩이 되어야만 한다.
- 이런 이유는 다형성의 표현에서 오버라이딩이 되었음을 의미하는 것인데 이것은 반드시 오버라이딩이 되어야만 한다.
- 여기서 중요한 것은 마지막에 세미클론으로 끝난다는 것이다. 즉, 내용부를 가지지 않고 이름만 있는 메서드이다.
- 접근_제한자 abstract 결과형_리턴값 메서드명(매개_변수들) throws 예외 클래스들;
- 추상메서드를 만드는 이유는 상속받는 하위 클래스에게 디자인이 되어 있는 메서드를 재정의 하라고 명령을 내리기 위해서다.
- 추상클래스를 통해 인스턴스를 발생시키려고 하면 에러가 발생한다.
- 접근_제한자 abstract class 클래스명 extends 상위_클래스 implements 상위_인터페이스{...}
- 인터페이스 : 단일 상속의 제약을 보완하기 위해 자바에서 제안한 새로운 개념의 클래스. 이를 통하 자바는 다중 상속을 할 수 있게 되었다.
- 접근_제한자 interface 인터페이스 명 extends 상위_인터페이스{ 내용부 }
[JPG image (1.51 MB)]
- 인터페이스는 다중 상속이 가능하다는 특징이 강하게 나타난다.
- 인터페이스의 정의
- 1. 다중 상속을 위한 클래스의 대안
- 2. 다형성에 의한 클래스 제어
- 1. 다중 상속을 위한 클래스의 대안
- 인터페이스의 내부에 포함 될 수 있는 멤버들은 일반 클래스와 조금 차이난다.
- 인터페이스 포함 멤버
- 필드 : 무조건 public static final 멤버 필드이다. 모두 기재하든 static만 기재하든 기재를 하지 않든 모두 public static final로 인식한다.
- 메서드 : 무조건 public abstract 멤버 메서드다. 고로 정의부를 가질 수 없다. 인터페이스도 다형성이 목절이므로 자동으로 모든 메서드가 abstract가 된다.
- 정적 중첩 클래스 : 인터페이스가 가지는 중첩 클래스에는 자동적으로 static이 붙어 정적 중첩 클래스만 가질 수 있다는 개념이 되어버린다. 물론 중첩 클래스 내부에는 일반 클래스처럼 할수 있다.(생성자 생성, 정의부가 있는 메서드 생성 등)
- 필드 : 무조건 public static final 멤버 필드이다. 모두 기재하든 static만 기재하든 기재를 하지 않든 모두 public static final로 인식한다.
- 인터페이스에는 생성자 조차 없다. 어떤 의미로는 제한적인 클래스라고 생각 할 수도 있다.
- 추상 메서드를 포함 하고 있고 생성자도 없어 객체를 발생 시킬 수 없다.
- 필드 : 인터페이스에서 필드를 사용하려면 직접 값을 할당하는 방식으로 한다.
- 필드 : 인터페이스에서 필드를 사용하려면 직접 값을 할당하는 방식으로 한다.
- 접근_제한자 interface 인터페이스 명 extends 상위_인터페이스{ 내용부 }
interface A1{ int w = 10; static int x = 20; final int y = 30; public static final int z = 40; } public class Round14_Ex01 { public static void main(String[] ar){ //A1 ap = new A1(); //A1.w = 100; System.out.println("w = " + A1.w); System.out.println("x = " + A1.y); System.out.println("y = " + A1.x); System.out.println("z = " + A1.z); } }
- 메서드 : 무조건 public abstract이기 때문에 무조건 하위 클래스에 의해 오버라이딩이 되어야 한다.
- 그리고 public 접근자가 생략되어 있으므로 오버라이딩 시에는 반드시 접근자를 public으로 해야 한다.
- 그리고 public 접근자가 생략되어 있으므로 오버라이딩 시에는 반드시 접근자를 public으로 해야 한다.
interface A2{ void aaa(); public abstract void bbb(); } class B2 implements A2{ void aaa(){ System.out.println("aaa 메서드"); } public void bbb(){ System.out.println("bbb 메서드"); } } public class Round14_Ex02 { public static void main(String[] ar){ B2 bp = new B2(); bp.aaa(); bp.bbb(); } }
- 정적 중첩 클래스 : 인터페이스에 마지막으로 있을 수 있는 멤버는 정적 중첩 클래스와 중첩 인터페이스이다. 클래스가 중첩 될 경우 무조건 public, static이기에 정적 중첩 클래스가 되는 것이다.
- 따라서 외부에서 그 클래스에 대한 객체를 발생시킬 때에는 정적 중첩 클래스 객체 생성 방식을 따르게 된다.
- 따라서 외부에서 그 클래스에 대한 객체를 발생시킬 때에는 정적 중첩 클래스 객체 생성 방식을 따르게 된다.
interface T3{ int x = 100; class B3{ private int y; public B3(){ this.y = 200; } public void disp(){ System.out.println("x = " + x);//A.x System.out.println("y = " + y);//this.y } } } public class Round14_Ex03 { public static void main(String[]ar){ T3.B3 bp = new T3.B3(); bp.disp(); } }
- int x 역시 public static final 이기 때문에 disp() 메서드에서 사용할 수 있는 것이다.
- abstract와 인터페이스
- 공통점
- 1. 디자인의 개념으로 다형성을 표현하기에 아주 적당한 형태이다.
- 2. 객체를 발생 시킬 수 없다.
- 3. 추상 메서드를 포함하고 있고, 그 메서드를 오버라이딩을 해야만 하위 클래스의 객체가 발생한다.
- 4. 표현의 방식에서 효율성을 고려하여 다형적인 표현을 주목적으로 한다.
- 1. 디자인의 개념으로 다형성을 표현하기에 아주 적당한 형태이다.
- 차이점
- 공통점
- 만약 단지 하위클래스들을 통합 관리하기 위한 목적만 있고 상위 클래스로서 아무런 역할도 할 필요 없다면 abstract보다는 인터페이스가 더 효율적이다.
5. 과제 ¶
- 그 동안 배운 개념(상속, 다형성 등)을 활용해서 도서 관리 프로그램 만들기
- 적어도 지정한 기능을 구현해서 프로그램이 동작하도록 하게 하면 된다.
- 조건
- 도서관리 클래스를 다형성을 통해서 코딩하기
- 상속 이용할 것
- 도서관리 클래스를 다형성을 통해서 코딩하기
도서관리 프로그램_v1.0 ========= 데이터 구조 ========= 회원 - 이름 - 생년월일 - 전화번호 - 대출내역 도서 - 제목 - 저자 - 출판사 - 고유코드 - 현재 비치수 ========= 구현해 기능 ========= 회원 - 등록 - 수정 - 도서 대출 가능 확인(대출제한 건수, 기한, 연속 대출) - 탈퇴 도서 - 대출 - 반납 - 책 상태 (대출가능 여부) - 책 정보 확인
5.1. 유재범 ¶
package hanjagonghomework; import hanjagonghomework.Active.Book2; import hanjagonghomework.Active.Member2; import java.io.*; interface Active{ public class Member implements Active{ public Member(){}; int arrcount = 0; String name = "유재범"; String birth = "1995년 12월 17일"; String phnum = "01068267677"; public String saveMemberData[][] = {{name, birth, phnum}}; public int rentcount = 0; } public class Member2 extends Member implements Active{ private static BufferedReader in; static{ in = new BufferedReader(new InputStreamReader(System.in)); } Member2(){}; public void getname(String name) throws IOException{ System.out.print("이름을 입력해 주십시오 : "); name = in.readLine(); saveMemberData[arrcount][0] = name; } public void getbirth(String birth) throws IOException{ int year = 0; int month = 0; int date = 0; boolean booly = false; do{ booly = false; try{ System.out.print("태어난 연도는? "); year = Integer.parseInt(in.readLine()); }catch(NumberFormatException nfe){ System.out.println("잘못된 연도입니다."); booly = true; } }while(booly); do{ booly = false; try{ System.out.print("태어난 달은? "); month = Integer.parseInt(in.readLine()); }catch(NumberFormatException nfe){ System.out.println("잘못된 달입니다."); booly = true; } }while(booly); do{ booly = false; try{ System.out.print("태어난 날짜는? "); date = Integer.parseInt(in.readLine()); }catch(NumberFormatException nfe){ System.out.println("잘못된 날짜입니다."); booly = true; } }while(booly); birth = year + "년 " + month + "월 " + date + "일"; saveMemberData[arrcount][1] = birth; } public void getphnum(String phnum) throws IOException{ System.out.print("전화번호를 입력해주세요 : "); phnum = in.readLine(); saveMemberData[arrcount][2] = phnum; } public String setname(){ return name; } public String setbirth(){ return birth; } public String setphnum(){ return phnum; } public void Addmem() throws IOException{ Member2 admem = new Member2(); arrcount++; admem.getname(name); admem.getbirth(birth); admem.getphnum(phnum); } public void Watchmem(){ for(int pp=0; pp<arrcount; pp++){ System.out.println("회원 이름 : " + saveMemberData[pp][0]); System.out.println("생년월일 : " + saveMemberData[pp][1]); System.out.println("핸드폰번호 : " + saveMemberData[pp][2]); System.out.println(); System.out.println(); } } } public class Book implements Active{ String book = "푸른 지붕의 앤"; String writer = "Lucy Maud Montgomery"; String bocom = "NEXUS"; public String [][] saveBookData = {{"푸른 지붕의 앤", "Lucy Maud Montgomery", "NEXUS", "", ""}}; public int bookarrcount = 0; int bocode = 1234; int bocount = 2; int rentcode = 0; } public class Book2 extends Book implements Active{ private static BufferedReader in; static{ in = new BufferedReader(new InputStreamReader(System.in)); } Book2(){}; int count=0; public void getbook(String book) throws IOException{ System.out.print("책 이름을 등록해주세요 : "); book = in.readLine(); saveBookData[bookarrcount][0] = book; } public void getwriter(String writer) throws IOException{ System.out.print("저자를 등록해주세요 : "); writer = in.readLine(); saveBookData[bookarrcount][1] = writer; } public void getbocom(String bocom) throws IOException{ System.out.print("출판사를 등록해주세요 : "); bocom = in.readLine(); saveBookData[bookarrcount][2] = bocom; } public String setbook(){ return book; } public String setwriter(){ return writer; } public String setbocom(){ return bocom; } public int setbocode(){ return (bocode+count); } public int setbocount(){ return bocount; } public void bookRent(){ if(bocount <= 0){ System.out.println("책을 대여하실 수 없으십니다."); } else{ bocount--; rentcode ++; } } public void bookReturn(){ if(bocount >= 2){ System.out.println("반납하실 책이 없읏비니다."); } else{ rentcode --; bocount++; } } public void WatchBookInfo() throws IOException{ Book2 watbok = new Book2(); watbok.getwriter(writer); watbok.getbook(book); watbok.getbocom(bocom); count++; } public void setBookInfo(){ System.out.println("책 제목 : " + book); System.out.println("저자 : " + writer); System.out.println("출판사 : " + bocom); System.out.println("고유 코드 : " + bocode+count); System.out.println("잔여 도서량 : " + bocount); } } } public class Library { public static void main(String[] args) throws IOException{ BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); Member2 memmenu = new Member2(); Book2 bookmenu = new Book2(); while(true){ boolean boolmenu = false; int menunum = 0; System.out.print("무엇을 하시겠습니까?" + "(1.회원증 생성 " + "2.회원 정보 확인 " + "3.책 정보 입력 " + "4.책 정보 확인 " + "5.책 대여 " + "6.책 반납) : "); do{ boolmenu = false; }while(boolmenu); try{ menunum = Integer.parseInt(in.readLine()); if(menunum > 6 || menunum <= 0){ System.out.println("잘못된 숫자입니다."); boolmenu = true; } }catch(NumberFormatException nfe){ System.out.println("잘못된 숫자입니다."); boolmenu = true; } if(menunum == 1){ memmenu.Addmem(); continue; } else if(menunum == 2){ memmenu.Watchmem(); continue; } else if(menunum == 3){ bookmenu.WatchBookInfo(); continue; } else if(menunum == 4){ bookmenu.setBookInfo(); continue; } else if(menunum == 5){ bookmenu.bookRent(); continue; } else if(menunum == 6){ bookmenu.bookReturn(); continue; } } } }
- 반복을 넣긴 했는데 책을 등록할 때, 회원 등록 할 때 그걸 저장해서 나중에 불러오고 싶었으나 어떻게 할 줄 몰라 실패
- 회원 정보나 책 정보를 넣으면 들어가기는 하는데 나중에 뽑을 때 초기 값으로 나온다. 왜이러지?
- 기타 필요 없거나 하나로 통일 될 수 있는 기능은 통일했습니다. 쓸데없이 여러가지 같은거 넣을 필요는 없을거 같았습니다.
- 생각해보니 다형성 쓸 필요가 없었습니다.
- 인터페이스를 main 클래스에서 받아서 쓰려니까 오류가 났는데 질문을 할 수도 없고 해서 그냥 import로 받았는데 이거 왜이러는지 아시는분 답변좀요.
- 하면 재밌는데 하기 전에 진짜 죽어도 하기 싫어서 큰일 날뻔했습니다.
- 다른 사람은 몰라도 김용준 과제 안하면 간식 사와라...
- 고쳐왔는데 결국 저장이 되도 계속 날라가네... 이 이상을 다른 선배님들께 물어봐도 내 코드가 잘못됬다는데 누구 코드좀 봐줄 사람 없으신가?