일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- import data
- csv
- github clone
- MySQL
- Visual Studio Code
- database
- 오류
- Python
- 에러
- localhost
- error 해결
- error
- 깃 토큰
- run sql script
- 클론
- visualstudio code
- jupyter
- vscode
- cmd
- 따옴표 삭제
- 파이썬
- PHPStorm
- DataGrip
- php
- 데이터베이스
- console창
- 단축키
- clone
- OrCAD 다운로드
- github token
- Today
- Total
개발 노트
7/25 Communication Cost, Debug, 상속, OverRiding, 인터페이스, implements, 추상 메소드 본문
7/25 Communication Cost, Debug, 상속, OverRiding, 인터페이스, implements, 추상 메소드
hayoung.dev 2022. 7. 25. 20:08[Communication Cost]
커뮤니케이션 비용 = N * (N-1) / 2
N은 사람수.
[Debug하는 방법]
1. Debug하려는 줄 > 오른쪽 마우스 >
를 하면 오른쪽에 표시가 된다.
많이 사용하진 않지만 시스템 내부 메모리 구조를 보고 싶을 때 가끔씩 사용. 시스템이 복잡해져서 내가 메모리를 잘 찾지 못할 때 사용.
[7. 자바 상속-중첩 Class]
p.2 상속의 정의와 장점
- 기존의 클래스를 재사용해서 새로운 클래스를 작성
- 두 클래스를 조상과 자손으로 관계를 맺어주는 것
- 자손은 조상의 모든 멤버를 상속받는다. (생성자, 초기화블럭 제외)
- 자손의 멤버개수는 조상보다 적을 수 없다. (같거나 많다.)
p.3 클래스간의 관계 - 상속관계
- 공통부분은 조상에서 관리하고 개별부분은 자손에서 관리
- 조상의 변경은 자손에 영향을 미치지만, 자손의 변경은 조상에 아무런 영향을 미치지 않는다.
p.4 상속(클래스간의 관계)
부모클래스(객체)의 멤버들을 자식클래스(객체)가 물려받는것
1. 상속을 사용하는 이유 : 기존에 만들어놓은 클래스의 재사용(=Reuse), 확장을 위해 사용.
2. 자바에서는 단일상속만이 가능하다(부모클래스가 한 개만 가능)
3. 부모클래스(super)와 자식클래스(sub)가 존재한다.
4. 자바에서 제공되어지는 모든 클래스들은 Object 라고 하는 최상위 클래스로부터 상속되어진다.
5. 사용자정의 클래스들도 Object 클래스라는 최상위클래스를 상속 받음
ch07 > Car2.java
package ch07;
public class Car2 {
int a = 7;
void move() {
System.out.println("차 이동...");
}
}
//상속받은 메소드를 OverRiding 한 것임. 부모 등에 OverRiding 했다고 생각하기.
//OverLoading과 OverRiding의 차이점 알아두기.
//OverLoading은 같은 class 내에서 메소드 이름이 똑같지만 파라미터의 타입이나 갯수로 메소드들이 구별되어 자동으로 출력되는 것이다.
//OverRiding은 부모클라스를 상속받아 부모의 등에 업혀서(Riding되어) 수행되는 것이다.
class Bus extends Car2 {
int a = 25;
void move() {
System.out.println("40명 태우고 이동");
}
}
class Ambulance extends Car2 {
int a = 100;
void move() {
System.out.println("사이렌 울리며 이동");
}
void special() {
System.out.println("환자를 태우고 있다.");
}
}
class FireEngine extends Car2 {
int a = 11;
void move() {
System.out.println("물뿌리면서 이동");
}
}
Car2Ex.java
package ch06;
class Car2 {
String name;
String color;
int speed;
//외우기
//생성자는 클래스명과 메소드명이 같다. 하지만 void라 하지 않는다.
//생성자의 역할은 메모리를 생성시켜준다. 기본생성자가 아닌 것은 멤버변수의 값을 세팅시켜서 초기화시켜준다.
Car2(String name, String color, int speed) {
//이름이 같으면 지역변수로 세팅되기 때문에 this연산자를 세팅해줘야 인스턴스변수(코드상 4~6줄)를 뜻한다는 것을 알 수 있다.
//this 인스턴스는 자신을 가리키는 참조변수
//모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재
//인스턴스변수와 지역변수를 구별하기 위해 참조변수 this사용
//헷갈리지 않도록 생성자에 this라는 참조변수를 쓰는 것을 권장.
//파라미터의 name을 가리키는 건지 멤버변수의 name을 가리키는 건지 모름. this를 쓰면 '나' 즉 나의 멤버변수를 뜻하는 것.
this.name = name;
this.color = color;
this.speed = speed;
}
void print() {
System.out.println(name +"\t" + color + "\t" + speed);
}
}
public class Car2Ex {
public static void main(String[] args) {
Car2 c1 = new Car2("소나타","빨강",150);
c1.print();
}
}
출력 결과
Outer.java
package ch07;
public class Outer {
int width = 10;
int height = 10;
Outer(int width, int height) {
this.width = width;
this.height = height;
}
//method 앞에 붙는 것은 Return형이다.(알아두기)
public Inner getInner() {
return new Inner();
}
class Inner { //class 안에 class가 있는 형태. Outer class가 존재할 때만 Inner 클래스를 쓸 때 이렇게 해둠.
int depth = 10;
public int volume() {
return width * height * depth;
}
}
}
OuterEx.java
package ch07;
public class OuterEx {
public static void main(String[] args) {
Outer out1 = new Outer(100, 100);
Outer.Inner in1 = out1.getInner(); //메소드를 사용함
//class 안의 inner class를 정의할 수 있다.
System.out.println("부피 : " + in1.volume());
Outer out2 = new Outer(200, 200);
Outer.Inner in2 = out2.new Inner(); //메소드를 사용하지 않음
System.out.println("부피 : " + in2.volume());
}
}
출력 결과
Person2.java
package ch07;
public class Person2 {
private String name;
private int age;
Person2(String name, int age) {
this.name = name;
this.age = age;
}
public void print() {
System.out.println("-----------");
System.out.println("이름 : " + name);
System.out.println("나이 : " + age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Student2.java
상속받을 때 SuperClass 오른쪽의 Browse를 눌러서 상속받을 코드를 지정해준다.
package ch07;
public class Student2 extends Person2 {
private String sno; //학번
Student2(String name, int age, String sno) { //자동완성으로 작성하기.
super(name, age); //부모
this.sno = sno; //나(자식)
}
public void print() {
super.print();
//내 것은 내가 처리한다.
System.out.println("학번 : "+sno);
}
public String getSno() {
return sno;
}
public void setSno(String sno) {
this.sno = sno;
}
}
class Teacher2 extends Person2{
private String subject;
Teacher2(String name, int age, String subject) { //자동완성으로 작성하기.
super(name, age);
this.subject = subject;
}
public void print() {
super.print();
System.out.println("과목 : " + subject);
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
}
class Manager2 extends Person2 {
private String part;
Manager2(String name, int age, String part) { //자동완성으로 작성하기.
super(name, age);
this.part = part;
}
public void print() {
super.print();
System.out.println("담당 : " + part);
}
public String getPart() {
return part;
}
public void setPart(String part) {
this.part = part;
}
}
Person2Ex.java
package ch07;
//실행은 부모와 같은 이름의 자식 메소드가 실행 (자식 메소드 수행)
//부모 rv = new 자식(); up casting OK
//부모 method()와 자식 method() 이름을 같을 때는 자식 메소드 실행
//부모의 멤버변수와 자식의 멤버변수가 이름이 같을 때는 부모 멤버변수 실행(*class 내에 선언되는 변수가 멤버변수)
//자식 rv2 = new 부모(); down casting X
//자식 rv3 = (자식)부모객체; down casting. 부모타입을 자식타입으로 변환하는 것.
//강제 형변환 하면
//1) 문법적 에러가 없음
//2) 에러가 있을 때도 없을 때도 있다
//그래서 권장하지 않는다.
public class Person2Ex {
public static void main(String[] args) {
Person2[] ps = new Person2[5];
ps[0] = new Student2("옥주현", 23, "1203667");
ps[1] = new Student2("김유신", 53, "1386889");
ps[2] = new Teacher2("대조영", 48, "JAVA");
ps[3] = new Manager2("조정은", 28, "뮤지컬");
ps[4] = new Manager2("전현무", 40, "MC");
for (Person2 p : ps) {
p.print();
//과제 - Manager2 객체 비교해서 manager가 맞다면 m.getPart() 출력
//instanceof 연산자 : 객체가 어떤 타입인지 조사할 때 사용. 주로 강제타입 변환에 변환이 가능한지 조사할 때 사용.
if (p instanceof Manager2) {
Manager2 m = (Manager2) p;
System.out.println("추가 : " + m.getPart());
System.out.println("2번째 방법 : " +((Manager2)p).getPart());
//32줄이 30+31줄과 같음.
}
}
}
}
Super1.java
package ch07;
//자식과 부모의 변수이름이 같을 때 각각 불러오는 방법
//근데 보통 자식과 부모는 멤버변수 이름을 굳이 같게 사용하지 않는다. 헷갈리기 때문임.
class Parent {
int a = 7;
int b = 7;
void display() {
System.out.println("Parent 대박");
}
void print() {
System.out.println("Parent 난 부모 print 메소드");
}
}
class Child extends Parent {
int a = 10;
void print() {
super.print(); //1. 부모 Method를 찾는다.
System.out.println("Child 부모멤버 a = " + super.a); //부모를 불러올 때는 super.를 사용
System.out.println("Child 난 자식 메소드 a = " +a); //내 클래스 안에선 this를 생략할 수 있음. This가 생략된 것으로 봄. 내껄 호출하고 싶으면 this. 를 붙이면 됨.
System.out.println("Child 난 자식 메소드 b = " +b);
System.out.println("=========================");
}
}
public class Super1 {
public static void main(String[] args) {
Child child = new Child();
child.print();
child.display();
}
}
출력 결과
Super2.java
package ch07;
class Parent1 {
Parent1() {
System.out.println("매개변수 없는 부모 생성자");
}
Parent1(String str) {
System.out.println("Parent 매개변수 있는 부모생성자 1 str-->" + str);
}
void parentPrint() {
System.out.println("parentPrint 야호! 월요일이다");
}
}
class Child1 extends Parent1 {
Child1() {
super("헐~!");
System.out.println("매개변수 없는 자식 생성자");
//super("헐~!"); //매개변수 1개짜리 부모 생성자를 또 호출하면 오류남. 왜냐면 위에서 이미 했기 때문.
}
void childCc1() {
System.out.println("cc1 야호! 월요일이다");
}
void childCc2() {
System.out.println("cc2 자식 Method cc2");
}
}
public class Super2 {
public static void main(String[] args) {
Child1 child1 = new Child1();
child1.childCc2();
child1.childCc1();
//chidl1.super.cc1(); //이렇게 하면 오류남.
}
}
호출 춘서는 Child1 > Parent1 이지만 실행 순서(출력 결과)는 Parent1 > Child1 이다.
부모 클래스의 "기본 생성자"를 자동으로 호출하게 된다.
출력 결과
Super3.java
package ch07;
//실제로는 이렇게 코드를 짜지 않지만 생성자의 흐름을 보기에 좋음.
class Parent3 {
Parent3() {
System.out.println("1. 매개변수 없는 조상 생성자 Parent3");
}
Parent3(int x) {
this(); //자기 자신 class의 생성자
System.out.println("매개변수 1개 Parent3 : x = " + x);
}
}
class Child3 extends Parent3 {
Child3(int x) { //Parent3 기본 생성자
System.out.println("2. Child3 매개변수 1개 Child3: x = " + x);
}
Child3(int x, int y) {
this(x); //자신 class의 1개 매개변수 생성자 -> 16줄 먼저 실행됨.
System.out.println("3. Child3 매개변수 2개 부모 : x = " + x + " , y " +y);
}
}
class Child5 extends Child3 {
Child5(int x, int y) {
super(x, y); //Child3 Class의 2개 매개변수 생성자
System.out.println("4. Child5 매개변수 2개 자식 : x = " + x + " , y " + y);
}
void cc5() {
System.out.println("Child5 cc5 메소드...");
}
}
public class Super3 {
public static void main(String[] args) {
Child5 child5 = new Child5(7, 15);
}
}
출력 결과
지금까지 extend를 해본 것임. Implements를 할 차례. 인터페이스는 일종의 추상클래스. 추상클래스를 구현하는 것이 Implements임.
[8. 자바 추상 Interface]
p.14
인터페이스는 구현된 것이 전혀 없는 것이다.
1) 일종의 추상클래스. 추상클래스(미완성 설계도)보다 추상화 정도가 높다.
2) 실제 구현된 것이 전혀 없는 기본 설계도.(알맹이 없는 껍데기)
3) 추상메서드와 상수만을 멤버로 가질 수 있다.
4) 인스턴스를 생성할 수 없고, 클래스 작성에 도움을 줄 목적으로 사용된다
5) 미리 정해진 규칙에 맞게 구현하도록 표준을 제시하는 데 사용된다
6) class’대신 ‘interface’를 사용한다는 것 외에는 클래스 작성과 동일하다
p.15
- 모든 멤버변수는 public static final이어야 하며, 이를 생략할 수 있다.
- 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다.
(보통 생략이 가능하면 대부분 생략함.)
p.16
- 인터페이스는 클래스와 달리 다중상속을 허용한다.
- 인터페이스는 Object 클래스와 같은 최고 조상이 없다.
p.17
인터페이스 구현 : 클래스를 상속받는 것과 같다. 다만 extend 대신 implements를 사용한다.
class 클래스이름 implements 인터페이스 {
}
p.20 인터페이스의 장점
1. 개발시간을 단축시킬 수 있다.
- 일단 인터페이스가 작성되면, 이를 사용해서 프로그램을 작성하는 것이 가능. 메서드를 호출하는 쪽에서는 메서드의 내용에 관계없이 선언부만 알면 되기 때문.
- 동시에 다른 한 쪽에서는 인터페이스를 구현하는 클래스를 작성하도록 하여, 인터페이스를 구현하는 클래스가 작성될 때까지 기다리지 않고도 양쪽에서 동시에 개발을 진행
2. 표준화가 가능하다.
- 프로젝트에 사용되는 기본 틀을 인터페이스로 작성한 다음, 개발자들에게 인터 페이스를 구현하여 프로그램을 작성하도록 함으로써 보다 일관되고 정형화된 프로그램의 개발이 가능.
3. 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.
- 서로 상속관계에 있지도 않고, 같은 조상클래스를 가지고 있지 않은 서로 아무런 관계도 없는 클래스들에게 하나의 인터페이스를 공통적으로 구현하도록 함으로써 관계를 매핑.
4. 독립적인 프로그래밍이 가능하다.
- 인터페이스를 이용하면 클래스의 선언과 구현을 분리시킬 수 있기 때문에 실제 구현에 독립적인 프로그램을 작성하는 것이 가능
- 클래스와 클래스간의 직접적인 관계를 인터페이스를 이용해서 간접적인 관계로 변경하면, 한 클래스의 변경이 관련된 다른 클래스에 영향을 미치지 않는 독립적인 프로그래밍이 가능
ch08 > Inter1.java
(마우스 우클릭 > new > interface)
package ch08;
public interface Inter1 {
//Static Final. 마지막 변수이므로 수정할 수 없음. 인터페이스에 있는 변수는 전부 상수이다.
int AAA = 3;
//추상메소드(Abstract methods)
//인터페이스의 메소드들은 전부 추상 메소드이다.
void display();
void print();
}
//Inter1을 상속받아서 ImplClass1을 구현하겠다는 뜻.
class ImplClass1 implements Inter1 {
@Override
public void display() {
//AAA++; 값을 더이상 할당할 수가 없다. 그래서 오류 남.
System.out.println("재정의 했어..AAA->" + AAA);
}
@Override
public void print() {
System.out.println("Interface 상속받아 구현");
}
}
Inter1Ex.java
package ch08;
public class Inter1Ex {
public static void main(String[] args) {
ImplClass1 implClass1 = new ImplClass1();
implClass1.display();
implClass1.print();
}
}
출력 결과
Inter2.java
package ch08;
interface Interfa2 {
void ifa2(); //추상 메소드
}
//인터페이스를 상속받는데 구현이 아니고 확장이기 때문에 Implements를 쓰지 않고 extends를 쓰는 것이다.
//interface를 interface로 상속받을 때 extends를 쓴다.
interface Interfa21 extends Interfa2 {
void ifa21(); //추상 메소드
}
//interface만 계속 확장되는 중
interface Interfa22 extends Interfa21 {
void ifa22(); //추상 메소드
}
//앞이 클래스면 여기있는 것들을 구현해야 하기 때문에 implements를 쓰는 것임.
//interface를 class로 상속받을 때 implements를 쓴다.
//위와 헷갈리면 안됨.
class ImplClass2 implements Interfa22 {
@Override
public void ifa21() {
System.out.println("ImplClass2 Interfa21의 매소드");
}
@Override
public void ifa2() {
System.out.println("ImplClass2 Interfa2의 매소드");
}
@Override
public void ifa22() {
System.out.println("ImplClass2 Interfa22의 매소드");
}
}
public class Inter2 {
public static void main(String[] args) {
ImplClass2 implClass2 = new ImplClass2();
implClass2.ifa2();
implClass2.ifa21();
implClass2.ifa22();
System.out.println("-----------Interfa21 interfa21 사용가능 범위------------");
Interfa21 interfa21 = new ImplClass2(); //부모에게 자식을 개입할 수 있다.
interfa21.ifa21();
//interfa21.ifa22(); //21을 상속받아서 22가 만들어졌기 때문에 못 쓴다.
}
}
출력 결과
Abstract1.java
추상클래스 만들 때 abstract 찍기
package ch08;
abstract class AbsClass {
int kkk = 0;
public void setKkk(int kkk) {
this.kkk = kkk;
}
public AbsClass() {
System.out.println("추상 Class 생성자");
}
//추상 클라스는 하나 이상의 추상 메소드가 존재해야 한다.
abstract void print();
}
class ImplAbsClass extends AbsClass {
//추상메소드를 상속받으면 반드시 구현해야 한다. 단 인터페이스를 상속받으면 인터페이스이기 때문에 구현할 필요 없다.
@Override
void print() {
System.out.println("ImplAbsClass + kkk --->" + kkk);
}
}
public class Abstract1 {
public static void main(String[] args) {
//추상 Class는 instance 생성 안됨.
//AbsClass absClass = new AbsClass();
AbsClass absClass = new ImplAbsClass();
absClass.setKkk(12);
absClass.print();
}
}
출력 결과
인터페이스와 추상클래스 비교 문제 면접에 많이 나옴.(중요 외우기, 면접 단골 손님 별 3개)
추상클래스는 변수와 메소드와 추상메소드로 구성되어 있고, 인터페이스는 상수와 추상메소드로 구성되어 있다.
추상클래스는 상속받을 때 extends 키워드를 사용, 인터페이스는 implements(구현하다) 키워드를 사용한다.
선언 구문 외우기.
두 개의 공통점은 overRiding.
추상클래스는 단일상속만 가능하고 인터페이스는 다중상속이 가능하다.
Lenderable.java
package ch08;
//인터페이스이기 때문에 메소드들은 전부 추상 메소드이다.
public interface Lenderable { //대여 가능 인터페이스
//인간이 이해할 수 있는 용어로 바꿔줄 때 상수를 쓰기도 함.
//인터페이스이기 때문에 얘네들은 상수이다.(추상 메소드라서)
int BORROW = 1; //빌려간 상태
int NORMAL = 0; //대여 가능한 상태
void checkOut(String borrower, String date);
void checkin();
}
class SeperateVolume implements Lenderable{
String title; //초기 생성 시 값 입력됨.
String date;
String borrower;
int status; //상태값 (기본값 0)
SeperateVolume(String title) {
this.title = title;
}
@Override
public void checkOut(String borrower, String date) { //대여
if (status != NORMAL) return; //status의 초기값은 아무것도 없기 때문에 0이다.
this.date = date;
this.borrower = borrower;
status = BORROW;
// BORROW = 1; 안됨
System.out.println(borrower + "가 " + date + "일에 " + title+ "을 대여했다.");
}
@Override
public void checkin() { //반납
System.out.println(borrower + "가 " + title+ "을 반납했다");
//전부 초기화
date = null;
title = null;
borrower = null;
status = NORMAL; //0
}
}
LendarableEx.java
package ch08;
public class LendarableEx {
public static void main(String[] args) {
SeperateVolume sv = new SeperateVolume("젊은 베르테르 슬픔");
sv.checkOut("정승환/박윤하", "2022/07/25");
sv.checkin();
}
}
출력 결과
부모와 자식 예제 한 개 더
class Super {
int index = 5;
public void printVal() {
System.out.println("Super");
}
}
class Sub extends Super {
int index = 2;
public void printVal() {
System.out.println("Sub");
}
}
public class Exam {
public static void main(String[ ] args) {
Super sup = new Sub();
System.out.print(sup.index + " ");
sup.printVal();
}
}
부모 method()와 자식 method() 이름을 같을 때는 자식 메소드 실행
부모의 멤버변수와 자식의 멤버변수가 이름이 같을 때는 부모 멤버변수 실행(*class 내에 선언되는 변수가 멤버변수)
출력 결과 : 5 Sub