인터페이스(Interface)
"나는 이름만 줄테니 네가 알아서 정의해"
다른 클래스를 작성할 때 기본이 되는 툴을 제공하고 그 사이의 중간 매개 역할까지 담당하는 추상클래스를 의미한다. 그럼 implements로 받아주는 클래스에서 정의를 하면 됨. 자바에서는 원래 다중상속을 지원하지 않지만 인터페이스를 통해서는 다중상속이 가능하다.
인터페이스는 오로지 추상메소드와 상수만을 포함하지만, 추상클래스는 추상메소드를 포함해 생성자, 필드, 일반 메소드도 포함하고 있다는 점이 큰 차이점이다. 그래서 abstract는 추상메소드에만 들어있음! 인터페이스에는 따로 해주지 않아도 컴파일러가 인식을 해준다.
인터페이스 문법
처음부터 Pakage Explorer -> New에서 생성할 때 클래스가 아니라 인터페이스에서 만들어야한다. 아이콘만 보더라도 인터페이스 라는 걸 알 수 있음!
접근제어자 interface 인터페이스명
{
public static final 타입 상수이름 = 값;
public abstract 메소드이름(매개변수 목록);
}
일반 메소드도 포함하고 있는 추상클래스와 달리 인터페이스의 경우 추상메소드만 있기 때문에 abstract제어자는 생략해도 컴파일러가 알아서 처리한다. 인터페이스의 경우 추상메소드의 선언부 밖에 없기 때문에 상속 받은 자식은 모드 메소드를 오버라이딩(재정의) 해줘야한다. 만약 인터페이스에서 5개를 선언했다면 자식도 똑같이 5개를 무조건!! 구현해줘야함
뒤에 나올 코드는 Window OS의 입장에서 정의한 코드이다. 그래픽카드 회사에게 이런 것들을 구현해 달라며 인터페이스로 요청하고 각 회사에서는 규격에 맞게 작성을 해서 보내준다는 걸 볼 수 있다.
이러한 작업을 하는 이유는? ...
인터페이스로 정해둔 규율이 없다면 여러 그래픽카드 회사들이 자사의 작성 방식에 맞게 작성해서 보낼 것이다. 받는 입장에서는 다 다른 방식으로 구현을 해야하기 때문에 시간과 비용이 많이 드니까 인터페이스로 추상메소드(선언부)만 정해준다. 나머지는 그래픽카드 회사들이 거기에 맞춰 만들고 납품을 하게 되는 것이다. 여기서 GraphicsCard라는 이름의 인터페이스가 윈도우OS와 그래픽카드를 잇는 역할을 함
Rgb -> PointColor -> GraphicsCard -> AmdRadeon, NvidiaGeForce -> GraphicsCardMain이 순으로 작성을 해주었고 흐름을 따라가는 게 공부하는데 도움이 된다.
Rgb
package sample2;
public class Rgb
{
private int red;
private int green;
private int blue;
public Rgb()
{
this(0, 0, 0);
}
public Rgb(int red, int green, int blue)
{
this.red = red;
this.blue = blue;
this.green = green;
}
public void setRed(int red)
{
this.red = red;
}
public int getRed()
{
return red;
}
public void setGreen(int green)
{
this.green = green;
}
public int getGreen()
{
return green;
}
public void setBlue(int blue)
{
this.blue = blue;
}
public int getBlue()
{
return blue;
}
}
그래픽카드에서 던져주는 색상값을 저장하기 위한 클래스이다. 안에서 어떻게 동작 하는지 외부에는 숨기기 위해서 Rgb·PointColor 모두 private 변수로 정의를 해준다. 처음 설정을 하게 되면 큰 기능은 없음
PointColor
package sample2;
public class PointColor
{
private int x;
private int y;
private Rgb rgb;
public PointColor()
{
this(0, 0, new Rgb());
}
public PointColor(int x, int y, Rgb rgb)
{
//super();
//PointColor의 조상은 Object
this.x = x;
this.y = y;
this.rgb = rgb;
}
public void setX(int x)
{
this.x = x;
}
public int getX()
{
return x;
}
public void setY(int y)
{
this.y = y;
}
public int getY()
{
return y;
}
public void setRgb(Rgb rgb) //매개변수 참조형
{
this.rgb = rgb;
}
public Rgb getRgb() //반환타입도 Rgb임
{
return rgb;
}
}
위의 Rgb 클래스와 크게 다른점은 없지만 특이한 사항이 있다면 변수 선언부분이다.
private Rgb rgb;
Rgb 클래스에 있는 정보들을 참조변수로 불러준다. 이렇게 참조변수로 불러준 경우 생성자나 메인에서도 pointColor를 이용해서 Rgb를 부를 때는 객체생성을 먼저 해줘야 한다. 변수 하나를 부르는 것이 아니라 그 안에 있는 객체들을 모조리 갖고 와야 하는 거니까 부를 때마다 설정을 해줘야 하는 것이다.
getRgb()의 경우 반환타입도 Rgb로 설정해준다. 그래야 다른 클래스에서 불렀을 때 Rgb의 주소를 태워서 보낼 수 있다.
GraphicsCard (Interface)
package sample2;
public interface GraphicsCard
{
//제조사
public String company();
//모델명
public String model();
//메모리
public int memory();
//풀력
public void write(PointColor pointColor);
}
각 제조사들이 작성해야 하는 틀을 만들어주는 부분이다. 추상메소드를 4개 선언 했다면 받는 쪽에서 무조건 이 4개를 재정의 해줘야한다. 출력부분에서는 PointColor 클래스를 매개변수로 받는다. 일반적인 클래스와 다른 것이 있다면 ...
public interface 인터페이스명 { }
클래스가 아니라 interface를 갖고있다. 추상메소드만 있기 때문에 abstract를 굳이 사용하지 않아도 컴파일러가 알아서 처리한다. 처음 패키지익스플로러에서부터 만들어 줄 때 클래스가 아니라 인터페이스로 만들면 쉽다!
AmdRadeon
package sample2;
public class AmdRadeon implements GraphicsCard
{
//제조사
private String company;
//모델명
private String model;
//메모리
private int memory;
//생성자
public AmdRadeon(String model, int memory)
{
company = "AMD";
//아예 정해져 있어서 매개변수로 받을 필요가 없음
this.model = model;
this.memory = memory;
}
//제조사
public String company()
{
return company;
}
//모델명
public String model()
{
return model;
}
//메모리
public int memory()
{
return memory;
}
//풀력
public void write(PointColor pointColor)
{
if(pointColor != null) //이것부터 시작함
{
Rgb rgb = pointColor.getRgb();
System.out.println("--- " + company + " GraphicsCard 출력");
System.out.println("1. color를 구성합니다.");
if(rgb != null)
{
System.out.println("Blue : " + pointColor.getRgb().getBlue());
System.out.println("Red : " + pointColor.getRgb().getRed());
System.out.println("Green : " + pointColor.getRgb().getGreen());
}
System.out.println("2. 좌표를 구합니다.");
System.out.println(" X : " + pointColor.getX());
System.out.println(" Y : " + pointColor.getY());
System.out.println("3. 모니터 좌표에 색상을 출력합니다.");
}
}
}
납품하는 회사쪽에서 WindowOS에서 요청한 추상메소드를 재정의하는 클래스이다. 클래스명 뒤에 'implements + 인터페이스명'을 써줘야하고, 모든 추상메소드를 구현해야만 오류가 사라진다.
생성자 부분의 경우 회사명은 이미 정해져 있기 때문에 매개변수로 받지 않는다.
write() 메소드
PointColor를 매개변수로 받아 준 이유는 이 안에 Rgb가 포함되어 있어서 하나만 불러와도 사용할 수 있기 때문임. 여기서 출력메소드를 사용하는 이유는 이 코드들이 연습용으로 만들어졌기 때문에 서로 연결이 잘 됐는지 확인하는 용도로 사용을 하는 것이다. 실제로는 이렇게 바로 출력하는 경우는 드물다고 함!
if(pointColor != null)
Rgb rgb = pointColor.getRgb();
Rgb 라는 방을 만든 뒤 시작주소를 넣었다. pointColor 안에 있는 getRgb() 메소드를 넣어준 것이다.
company로 인스턴스를 받았는데 만약 같은 클래스 안에 두 개 이상의 company가 있었다면 this.company로 인스턴스 변수임을 지정해야 한다.
if(rgb != null)
pointColor.getRgb().getBlue()
포인트컬러 내부에 있는 getRgb() 메소드 그리고 그 안에 있는 getBlue() 메소드를 호출한다.
다른 색상이나 좌표를 구할 때도 마찬가지임!!
NvidiaGeForce
package sample2;
public class NvidiaGeForce implements GraphicsCard
{
//제조사
private String company;
//모델명
private String model;
//메모리
private int memory;
//생성자
public NvidiaGeForce(String model, int memory)
{
company = "NVIDIA";
this.model = model;
this.memory = memory;
}
//return 타입은 get 느낌임
//제조사
public String company()
{
return company;
}
//모델명
public String model()
{
return model;
}
//메모리
public int memory()
{
return memory;
}
//출력
public void write(PointColor pointcolor)
{
if(pointcolor != null)
{
Rgb rgb = pointcolor.getRgb();
System.out.println("---" + company + "GraphicsCard 출력");
System.out.println("1. color를 구성합니다.");
if(rgb != null)
{
System.out.println("Blue : " + pointcolor.getRgb().getBlue());
System.out.println("Red : " + pointcolor.getRgb().getRed());
System.out.println("Green : " + pointcolor.getRgb().getGreen());
}
System.out.println("2. 좌표를 구합니다.");
System.out.println(" X : " + pointcolor.getX());
System.out.println(" Y : " + pointcolor.getY());
System.out.println("3. 모니터 좌표에 색상을 출력합니다.");
}
}
}
GraphicsCardMain
package sample2;
public class GraphicsCardMain {
public void operatingSystemWrite(GraphicsCard graphicsCard, PointColor pointcolor)
{
if(graphicsCard != null)
//인터페이스가 어딘가에 있다는 것
{
System.out.println("그래픽 카드 출력");
System.out.println("회사명 : " + graphicsCard.company());
System.out.println("모델명 : " + graphicsCard.model());
System.out.println("메모리 : " + graphicsCard.memory());
System.out.println("출력 순서");
graphicsCard.write(pointcolor);
}
}
public static void main(String[] args) {
//라데온그래픽 카드 생성
GraphicsCard amdRadeon = new AmdRadeon("Rx 5000", 4096);
//AmdRadeon amdRadeon = new AmdRadeon("Rx 5000", 4096);
//엔비디아 그래픽 카드 생성
NvidiaGeForce nvidiaGeForce = new NvidiaGeForce("Geforce GT 710", 2048);
//GraphicsCard nvidiaGeForce = new NvidiaGeForce("Geforce GT 710", 2048);
//포인트 컬러 생성
PointColor pointcolor = new PointColor();
//x,y,rgb도 들어있으니까
pointcolor.setX(100);
pointcolor.setY(200);
pointcolor.setRgb(new Rgb(255, 128, 100));
GraphicsCardMain graphicsCardMain = new GraphicsCardMain();
graphicsCardMain.operatingSystemWrite(amdRadeon, pointcolor);
System.out.println("");
graphicsCardMain.operatingSystemWrite(nvidiaGeForce, pointcolor);
}
}
//
그래픽 카드 출력 회사명 : AMD 모델명 : Rx 5000 메모리 : 4096 출력 순서 --- AMDGraphicsCard 출력 1. color를 구성합니다. Red : 123 Green : 234 Blue : 255 2. 좌표를 구합니다. X : 100 Y : 200 3. 모니터 좌표에 색상을 출력합니다. 그래픽 카드 출력 회사명 : NVIDIA 모델명 : Geforce GT 710 메모리 : 2048 출력 순서 --- NVIDIAGraphicsCard 출력 1. color를 구성합니다. Red : 123 Green : 234 Blue : 255 2. 좌표를 구합니다. X : 100 Y : 200 3. 모니터 좌표에 색상을 출력합니다. |
메인에서는 그래픽 카드가 채운 추상메소드를 받아서 구현을 해주는 역할을 하고 있다. 여기서 이 클래스는 그래픽카드를 읽어주는 운영체제인 것이다.
operatingSystemWrite()
매개변수 : 그래픽카드와 OS를 연결시켜 주는 것은 인터페이스 즉, GraphicsCard니까 먼저 받아준다. 그리고 x,y 좌표와 red, green, blue가 모두 담겨 있는 클래스인 PointColor를 받아준다.
company, model, memory 이런 값이 적혀있는 것은 제조사의 클래스인데 왜 GraphicsCard를 받아주지? 일반 클래스라면 상속을 받은 자식 클래스를 받아와서 불러줬을텐데 인터페이스가 둘 사이를 이어주는 매개체 역할을 하기 때문에 넣어주는 것이다!!
graphicsCard.write(pointColor)
operatingSystemWrite을 통해서 호출하기 전에 graphicsCard.write() 오버라이딩한 메소드를 화면에 찍어준다. 매개변수는 write()메소드로 선언을 할 때 넣어준 pointColor를 똑같이 넣어준 것 뿐이다.
main
라데온·엔비디아 그래픽카드 생성을 할 때 두 가지를 사용가능
GraphicsCard amdRadeon = new AmdRadeon("Rx 5000", 4096);
AmdRadeon amdRadeon = new AmdRadeon("Rx 5000", 4096);
아래는 우리가 지금껏 많이 봤던 방식
위쪽은 어떻게 작동이 되는 것일까? 답부터 말하자면 다형성이다! 조상클래스인 GraphicsCard에 자식 클래스인 AmdRadeon의 값을 받아서 넣어준다. 하지만 다형성의 공식으로 이 반대는 되지 않는다! AmdRadeon의 시작주소를 받아 주게 되는 것이다.
PointColor pointcolor = new PointColor();
각 제조사에서 model과 memory를 넣어 줬다면 모니터에 점을 찍어 줄 준비를 해야한다. 색상을 맡고 있는 클래스는 pointColor 클래스니까 객체생성을 해주고 각 값을 set()을 통해서 세팅해주어야 아래에서 출력할 수 있다.
pointcolor.setRgb(new Rgb(255, 128, 100));
인자값 안에 생성자를 만들어 주는 이유는 주소값을 세팅해주기 위해서인데 위쪽 PointColor 클래스 부분에서 했던 말이 있다. 반환타입도 Rgb로 설정하는 이유는 다른 클래스에서 불렀을 때 Rgb의 주소를 태워서 보낼 수 있기 때문이라고 그러려면 반환타입 뿐만 아니라 불러주는 setRgb에서도 주소값을 세팅해줘야한다.
GraphicsCardMain graphicsCardMain = new GraphicsCardMain();
opratingWrite를 사용하기 위해서는 인스턴스 객체이기 때문에 생성해주어야 한다.
graphicsCardMain.operatingSystemWrite(amdRadeon, pointcolor);
참조형변수 넘기기
위에서 Write를 세팅할 때는 인터페이스 부분을 매개변수로 넣었는데 여기서는 넘겨줄 정보들이 각 제조사 클래스에게 있으니까 제조사의 클래스를 넘겨준다. pointcolor는 똑같이 넘겨준다. 위에서 제조사의 객체생성을 하면서 값을 넘겨주지 않았다면 넣을 수 없다.
오늘의 TIP
조금 큰 회사에 들어가게 되면 업무팀이 세 가지로 나눠져 있다.
웹디자이너 / 코더 / 웹 개발자
코더 : 디자인을 잘라서 코드를 입혀줌 css 적용을 한다.
개발자 : 그걸 가지고 서버 연결을 집어 넣음
입사를 했을 때
회사의 환경에 맞게 적응을 해야하고, 업무 부서 파악이 가장 중요하다. 경험이 많은 사람의 경우 erd 테이블 관계도만 봐도 파악이 되지만 처음엔 그게 쉽지 않으니까 화면단위로 들어가서 기능별로 업무 파악을 해야한다. 이렇게 업무 단위로 분석을 해야 파악이 확실하게 됨
(웹서비스)개발자들은 정말 어려운 구현을 사용하는 게 아니다. 왜냐하면 유지보수가 힘들기 때문에 ... 근데 이런 흐름을 알아 가는 게 어렵다. 검색엔진의 경우 알고리즘을 직접 구현해줘야하기 때문에
'개발일지 > Java + Spring' 카테고리의 다른 글
[Spring] 흐름 읽기_1208필기 (0) | 2021.12.08 |
---|---|
[Spring] 스프링 환경&실행 경로 파악하기 (0) | 2021.12.07 |
211028(3) Java - 추상클래스 (0) | 2021.10.28 |
211028(1) Java - 접근제한자와 캡슐화 (4) | 2021.10.28 |
211027 java - 생성자에서 상수 초기화 (5) (0) | 2021.10.27 |