1. 학습 주제 : 접근제어자, 추상클래스, 상속, 오버라이딩, 인터페이스 이해하기
✔️접근제어자
- private : 해당 클래스 내에서만 접근 가능
- public : 모든 클래스에서 접근 가능
- default : (아무것도 적지 않았을 때) 같은 패키지 내에서만 접근 가능
- protected : 같은 패키지 내에서, 다른 패키지인 경우 자식 클래스에서 접근 가능 ( 상속 개념을 알아야함 )
✔️추상클래스
- 추상 클래스는 하나 이상의 추상 메서드를 포함하거나 단순히 상속을 위해 추상적으로 선언될 수 있는 클래스다.
- 클래스 선언에 'abstract' 키워드를 사용하여 추상 클래스를 정의한다.
- 추상 클래스는 직접 인스턴스화 될 수 없다.
( Abstract abs = new Abstract 가 안된다는 것.)
- 추상 클래스를 상속받는 모든 하위 클래스는 추상 클래스에 정의된 모든 추상메서드를 구현해야한다.
- 추상 클래스는 객체지향프로그래밍에서 추상화 원칙을 구현하는데 사용되고 코드의 재사용성을 높인다.
- 추상 메서드는 선언만 있고 구현이 없는 메서드다.
✔️상속
- 부모클래스의 것을 자식클래스가 가져다쓴다는 개념이다.
class Parent{
//부모클래스
}
class Child extends Parent{
//부모클래스를 상속받는 자식클래스
}
✔️상속 받는 것들
①메서드 : 부모클래스에 정의된 메서드를 자식클래스에서 재사용하고 확장할 수 있다.
②변수 : 단, 정적 변수(static)은 오버라이딩 할 수 없다.
③중첩 클래스: 부모 클래스 내에 정의된 중첩 클래스도 자식 클래스에 상속된다.
✔️상속 받지 않는 것들
①생성자: 생성자를 상속받지 않지만 자식클래스의 생성자에서 'super()'를 사용하여 부모클래스의 생성자를 호출한다.
②private 멤버 : 부모클래스의 private 멤버(변수나 메서드)는 자식 클래스에서 직접 접근할 수 없다.
✔️오버라이딩
- 자식 클래스에서 부모 클래스의 메서드를 재정의할 수 있다.
@Override 어노테이션을 꼭 써줘야한다. (주석이 아니라 시스템에 알려줘야하기 때문!)
✔️Interface (인터페이스)
- 자바는 단일 상속을 지원한다. 다중 상속을 지원하지 않기때문에 인터페이스가 필요하다.
- 클래스가 구현해야하는 '행동'을 정의한다.
- 추상화 : 인터페이스는 할 수 있는 것에 초점을 맞춘다.
interface What {
void play();
//인터페이스
}
class Example implements What {
public void play(){
System.out.println("인터페이스 구현")
}
}
✔️static final
- static : 인스턴스에 속하지 않는다. 이 멤버는 클래스의 모든 인스턴스에 의해 공유된다.
- final : 한 번 할당되면 값을 변경할 수 없음을 의미한다.
static final 조합은 상수를 정의하는 데 사용된다.
힙 메모리에 올라가지 않기 때문에 메모리를 알뜰히 쓰는데에 도움이 된다.
✔️생성자에 void를 쓰지 않는 이유
생성자의 주요 목적은 값을 반환하는게 아니라 새로운 객체를 초기화 하는 것이다.
생성자에 void가 있으면 생성자가 아니라 일반 메서드다.
2. 과제
3. 해결 과정
강사님께서 이 과제를 내주시며, 여태 배운 것을 총 망라하는 과제라고 하셨다.
코드를 짜기전에 대략적인 구조를 짜야한다.
설계없이 냅다 코드부터 짜면, 코드를 짜다 길을 잃게 된다.
마치 네비게이션없이 가는 초행길이랄까나?!
Duck은 모든 오리가 공통으로 가져야 할 코드를 가진 부모클래스다.
DuckFrame은 Frame (자바의 awt라이브러리에 있는 클래스)를 상속받아 그래픽을 표현하는데에 쓰일 클래스다.
Flyable, Quackable은 행위를 담은 인터페이스다.
(awt 라이브러리가 익숙치 않아서 기능 구현을 위한 메서드들은 gpt의 도움을 받았다.)
⭐부모클래스에서 자식클래스로 갈수록 구체화되어야 한다.
⭐생성자에서는 가독성을 위해 코드가 길어지는 것은 메서드로 따로 빼놓는 게 좋다.
4. 결과
Duck
package Day08_Interface;
import java.awt.*;
public abstract class Duck {//추상클래스는 추상메서드를 포함한다.
// 다른 클래스에서 Duck을 상속받아 추상메서드를 재정의(함수 오버라이딩)한다.
protected int x, y,size,index;
//protected 접근제어자는 같은 패키지 내에서, 다른패키지의 경우 자식 클래스에서 접근 가능.
public Duck(int x, int y,int size, int index){//Duck 생성자
this.x = x; //x좌표
this.y = y; //y좌표
this.size = size; //동그라미의 사이즈
this.index = index; //몇번째 출력된 오리인지 체크
}
public abstract void display(Graphics g);
public void swim(Graphics g){//모든 오리는 수영을 할 수 있기때문에 Duck클래스에 메서드를 생성.
g.drawString("수영",x-10,y-10);
}
}
MallardDuck
package Day08_Interface;
import java.awt.*;
public class MallardDuck extends Duck implements Quackable,Flyable{
public MallardDuck(int x, int y, int size, int index) {//생성자
super(x,y,size,index); //부모클래스의 생성자를 호출
}
@Override
public void display(Graphics g) { //오버라이딩
g.setColor(Color.BLUE);
g.fillOval(x,y,size,size);
g.drawString(String.valueOf(index)+"번째",x,y);
swim(g);
quack(g);
fly(g);
}
@Override
public void fly(Graphics g) {//인터페이스 메서드를 재정의한다.
g.drawString("날다",x-30,y+50);
}
@Override
public void quack(Graphics g) {
g.drawString("꽥꽥",x+60,y+15);
}
}
RedDuck
package Day08_Interface;
import java.awt.*;
public class RedDuck extends Duck implements Flyable,Quackable{
public RedDuck(int x, int y,int size,int index) {//생성자
super(x,y,size,index);
}
@Override
public void display(Graphics g) {
g.setColor(Color.RED);
g.fillOval(x,y,size,size);
g.drawString(String.valueOf(index)+"번째",x,y);
swim(g);
quack(g);
fly(g);
}
@Override
public void fly(Graphics g) {
g.drawString("날다",x-30,y+50);
}
@Override
public void quack(Graphics g) {
g.drawString("꽥꽥",x+60,y+15);
}
}
RubberDuck
package Day08_Interface;
import java.awt.*;
public class RubberDuck extends Duck implements Quackable{
public RubberDuck(int x, int y, int size, int index){
super(x, y, size, index);
}
@Override
public void display(Graphics g) {
g.setColor(Color.YELLOW);
g.fillOval(x,y,size,size);
g.drawString(String.valueOf(index)+"번째",x,y);
swim(g);
quack(g);
}
@Override
public void quack(Graphics g) {
g.drawString("삑삑",x+60,y+15);
}
}
DecoyDuck
package Day08_Interface;
import java.awt.*;
public class DecoyDuck extends Duck {
public DecoyDuck(int x, int y,int size, int index) {
super(x, y, size, index);
}
@Override
public void display(Graphics g) {
g.setColor(Color.GREEN);
g.fillOval(x,y,size,size);
g.drawString(String.valueOf(index)+"번째",x,y);
swim(g);
}
}
DuckFrame
package Day08_Interface;
import java.awt.*;
import java.util.Random;
public class DuckFrame extends Frame {
private Duck[] ducks = new Duck[20];
//20마리의 오리 고정크기 배열에 넣을 거임.
public static final int INITIAL_SIZE = 50; //상수는 static final로 정의
private static final int FRAME_WIDTH = 800;
private static final int FRAME_HEIGHT = 600;
public DuckFrame(){
setSize(FRAME_WIDTH,FRAME_HEIGHT);
setVisible(true);//디폴트가 false여서 true로 지정해줌.
makeDuck(); //가독성을 위해 메서드로 따로 빼줌.
}
public void makeDuck(){
Random rnd = new Random();
int maxX = FRAME_WIDTH - INITIAL_SIZE; //브라우저 크기가 바뀌든, 동그라미 크기가 바뀌든 변수 선언부에서만 수정하면 되도록 함.
int maxY = FRAME_HEIGHT - INITIAL_SIZE; //유지보수성을 높이는 부분.
for (int i = 0; i < ducks.length; i++) {
int x = rnd.nextInt(maxX);
int y = rnd.nextInt(maxY);
int duckType = rnd.nextInt(4); //타입을 (0~3)사이 숫자로 받는다.
switch(duckType){
case 0:
ducks[i] = new MallardDuck(x,y,INITIAL_SIZE,i);
break;
case 1:
ducks[i] = new RedDuck(x,y,INITIAL_SIZE,i);
break;
case 2:
ducks[i] = new RubberDuck(x,y,INITIAL_SIZE,i);
break;
case 3:
ducks[i] = new DecoyDuck(x,y,INITIAL_SIZE,i);
break;
}
}
}
@Override //Frame클래스에 있는 paint를 재정의한다.
public void paint(Graphics g) { //Window 기능이라 실행하면 브라우저 띄워짐.
for (Duck d : ducks) {
if (d != null) { //에러를 방지하기 위해 if문으로 null체크를 해준다.
d.display(g);
}
}
}
}
Flyable
package Day08_Interface;
import java.awt.*;
public interface Flyable { //인터페이스의 이름을 정할때, 뒤에 able을 붙인다.
void fly(Graphics g);
}
Quackable
package Day08_Interface;
import java.awt.*;
public interface Quackable { //인터페이스는 단순하다.
void quack(Graphics g);
}
Main
package Day08_Interface;
public class Main {
public static void main(String[] args) {
DuckFrame df = new DuckFrame();
}
}
5. 오늘의 회고
오히려 좋아
매일 숨가쁘게 이론+실습을 반복하다보니, 이해하기도 전에 과제를 해야하는 압박감에 스트레스를 받기도 했다.
지옥철을 타고 집으로 돌아가는 길에 수업이 벅차다는 좌절감이 몰려왔다.
그런데 곰곰히 생각해보니, 벅차게 배워보려고 온게 아닌가.
할 만한 과제와 들을 만한 수업이라면 내가 원하는 만큼 성장할 수 있을까..?
어렵다 느낄 때, 오히려 좋다는 마인드로 가보자.
'프로그래밍 언어 > Java' 카테고리의 다른 글
[과제] UML에 맞게 싱글톤 패턴 적용하기 (0) | 2023.12.18 |
---|---|
[Java] 싱글톤 패턴 개념 및 구현방법 (0) | 2023.12.18 |
[Java] 업캐스팅(Upcasting)과 다운캐스팅(Downcasting) (0) | 2023.12.18 |
[Java] StringBuilder 사용 이유 & 주요 메서드 (0) | 2023.12.17 |
[과제] 회원관리 - 객체지향프로그래밍 (1) | 2023.12.12 |