-
자바 100제 Part.3 / 14 ~ 23개발자 수업/인터넷 강의 2021. 9. 18. 16:17
1. 객체에 대한 참조값을 요소로 가지는 객체 배열을 생성하는 코드를 구현 (반복문 사용해서 객체 생성)
class Person{ //Field private String name; private int age; //Constructor Person(){} Person(String name, int age){ this.name=name; this.age=age; } //Method 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;} } public class Java100_oop_ObjArray{ public static void main(String[] args){ // 객체 생성 int[] ar1 = {1,2,3,4,5}; char[] ar2 = {'A','B','C','D','E'}; Person[] pa = new Person[5]; pa[0] = new Person("홍길동",20); pa[1] = new Person("박길동",21); pa[2] = new Person("김길동",22); pa[3] = new Person("장길동",23); pa[4] = new Person("고길동",24); // 출력 for(int i=0; i<pa.length; i++){ System.out.pritnln(pa[i].getName+" "); // 홍길동 박길동 김길동 장길동 고길동 } System.out.pritnln(); } }
2. 반복문을 사용하여 객체 배열을 생성하고 출력
class Person{ //Field private String name; private int age; //Constructor Person(){} Person(String name, int age){ this.name=name; this.age=age; } //Method 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;} } public class Java100_oop_ObjArray{ public static void main(String[] args){ // 객체 생성 Person[] pa; //Person 타입의 객체 배열 변수 pa 선언 pa = new Person[5]; //Person 객체의 참조값을 원소로 가지는 배열 공간 5개 생성 // 반복문 (for)을 돌면서 Person() 객체 생성 for(int i=0; i<pa.length; i++){ pa[i] = new Person(i+"번 후보자",i+20); //i만 입력하면 안 되고 문자열을 붙여서 문자열로 전달 // getter, setter 메서드 사용해서 출력 System.out.println(pa[i].getName() + " " + pa[i].getAge()); // 배열 인덱스 사용해서 출력 -> private 선언 삭제하고 사용해야 함 // System.out.println(pa[i].name + " " + pa[i].age); // printf() // System.out.pritnf("%s의 나이는 %d살 입니다.%n",pa[i].name,pa[1].age); } } }
3. 추상 클래스와 추상 메서드란 무엇인지 설명하고 관련된 예제 코드 구현
abstract class Animal{ // 구체적인 내용은 작성하지 않고 공통적인 특징을 추상적으로 선언 -> 리턴 값 조차도 없이 메서드명만 선언 abstract void cry(); void eat(){System.out.println("먹다.");} } class Dog extends Animal{ void cry(){System.out.println("멍멍");} } class Cat extends Animal{ void cry(){System.out.println("야옹");} } class Cow extends Animal{ void cry(){System.out.println("음메");} } class Animal2{ void fly(){System.out.println("날다.");} } public class Java100_oop_AbstractClassMethod{ public static void main(String[] args){ // 추상 클래스는 구체적인 내용이 없기 때문에 객체를 생성할 수 없다 Animal dog = new Animal(); // Err Animal2 dragonfly = new Animal2(); dragonfly.fly(); // 날다. // 추상 클래스 사용 -> 상속을 받아서 사용 // 추상(부모) 클래스를 상속받은 자식 클래스에서 해당 메서드를 오버라이딩하여 재정의한 후 사용 Dog dog = new Dog(); dog.cry(); // 멍멍 Cat cat = new Cat(); cat.cry(); // 야옹 Cow cow = new Cow(); cow.cry(); // 음메 } }
(1) Summary
추상(부모) 클래스는 다른 클래스들의 공통적인 특징을 변수나 메서드로 정의만 해놓은 것을 말한다 -> 추상 메서드
abstract를 앞에 붙이고 클래스 안에 추상 메서드를 포함하고 있다는 것을 제외하면 일반 클래스와 별반 차이 없다
Field, Constructor, Method도 포함할 수 있다
메서드 선언만 있고 구체적인 내용은 없으므로 객체를 생성할 수 없다
따라서 부모 클래스로서의 역할을 하지만, 구체적인 사용은 상속받은 자식 클래스에서 재정의(오버 라이딩)하여 사용해야 한다 -> 강제성
추상 클래스에서 선언만 해놓음으로써 이후 새로운(자식) 클래스들이 이를 상속받아 구현하므로 새로운 클래스를 작성할 때 하나의 틀이 된다
(2) 왜 쓰지?
우선 강제하기 위함이다
부모(추상) 클래스가 선언해놓은 메서드를 상속받은 자식 클래스들이 이름 그대로 재정의해서 구현하라고 강제하는 것이다
상속받은 자식 클래스 입장에서 자칫 상속만 받고 재정의해서 사용을 안 할 수도 있기 때문이다
즉, 일반 메서드로 구현하면 누군가는 해당 메서드를 구현 안 할 수도 있다
무조건 상속받은 자식 클래스 입장에서는 추상 메서드를 재정의해서 구현하도록 강제하기 위함이다
위의 cat 클래스에서 재정의한 cry() 메서드를 지우면 에러가 난다 -> 추상 메서드를 재정의(오버 라이딩) 하지 않아서
(3) 꼭 재정의(override)해야만 하는가?
일단 그렇다
자식 클래스는 일단은 무조건 부모(추상) 클래스로부터 상속받은 추상 메서드는 오버 라이딩해서 재정의 해야 한다
추상 메서드를 포함하고 있다면 곧 추상 클래스여야 한다
(3) 만약 재정의 하고 싶지 않다면?
자식 클래스에서 상속받은 추상 메서드를 구현하지 않는다면 자식 클래스도 abstract를 붙여서 추상으로 만들어준다
class 앞에 abstract를 붙인다
(4) 결론
부모(추상) 클래스에서 구현을 하지 않는 이유는 해당 메서드의 구현이 상속받는 클래스에 따라서 달라질 수 있기 때문에 선언만 해둔 것이다
마치 돈 많은 부모가 엄청난 대지만 상속해주고 용돈은 자식들이 알아서 사용하는 느낌
이러한 추상 클래스는 여러 명의 개발자가 작업할 때 코드의 확장과 분업을 효율적으로 처리할 수 있게 해 준다
분업화된 시스템에서 공통의 프로젝트를 진행할 때 많이 사용되는 중요한 문법이다
4. 자바의 인터페이스에 대해서 설명
[1] 인터페이스란 무엇인가
사전적 의미 : 결합부, 접속기 -> 사용자 간 또는 컴퓨터 간 통신이 가능하도록 해주는 디바이스나 프로그램
큰 틀에서 본다면 자바에서의 인터페이스 개념도 사전적 의미와 비슷하다
상호 간 통신을 위해서는 규격이 중요하다
이러한 규격을 인터페이스라 할 수 있고 인터페이스는 하나의 표준화를 제공하는 것
[2] 추상 클래스 vs 인터페이스
추상 클래스와 거의 비슷하다 -> 그러나 그 추상화 정도가 더 높다(더 엄격하다) -> 따라서, 일반 메서드 멤버 필드(변수)를 가질 수 없다
이러한 점들이 추상 클래스와 인터페이스 간 가장 큰 차이점 중 하나다
[3] 자바에서의 인터페이스 문법
표준화 및 규격을 인터페이스로 제공
따라서 어떤 클래스가 해당 인터페이스를 사용(상속)한다면 인터페이스에 선언되어있는 메서드를 구현해야 한다
인터페이스는 class 키워드를 사용하지 않고 별도의 interface 키워드를 사용
(class는 extends, interface는 implements)
추상 클래스와 같이 메서드의 구체적인 내용은 기술되어 있지 않으므로 인터페이스를 상속받은 클래스에서 재정의(오버 라이딩)하여 사용해야 한다
[4] 상속 vs 구현
클래스와 인터페이스 이 둘의 가장 큰 차이점 중 하나는 상속이다 -> a, b
자바에서 클래스는 단일 상속만 가능하지만, 인터페이스는 다중 상속이 가능하다 -> A, B 콤마로 분리
그러나 인터페이스에서는 extends 표현을 쓰지 않고 구현의 의미를 강조하는 implements 키워드를 사용하여 다중 상속을 구현한다
[5] 우선순위
extends 키워드가 항상 먼저 쓰임
class Student extends Person implements A, B
[6] 장점
인터페이스를 이용하면 메서드의 추상적인 선언과 그 메서드를 구체적인 구현 부분을 분리시킬 수 있다
하청을 주는 대기업(갑)은 하청업체(을)에 인터페이스만 제공 -> 각 하청업체(을)들이 이를 준수하여(=상속받아) 개발
5. 자바의 인터페이스 문법을 예제 코드로 구현
class Person{ //Field String name; int age; int weight; //Construtor Person(){} Person(String name, int age, int weight){ this.name = name; this.age = age; this.weight = weght; } //Method void wash(){System.out.println("씻다.");} void study(){System.out.println("공부하다.");} void play(){System.out.println("놀다.");} } interface Allowance{ //Field //변수는 안 되고 상수는 되므로 상수로 지정해주면 됨 -> public static final 붙이면 됨 //인터페이스 내 모든 멤버 필드(변수)는 public static final이어야 함 -> 생략이 가능 -> 그냥 "타입 상수명" 지정해서 쓰면 됨 public static final String aaa="코리아"; int bbb=100; //이렇게 써도 된다는 얘기 //Abstract Method //인터페이스 내 모든 메서드는 public abstract이어야 함 -> 생략이 가능 public abstract void in(int price, String name); void out(int price, String name); //이렇게 써도 된다는 얘기 } interface Train{ //Abstract Method abstract void train(int training_pay, String name); } class Student extends Person implements Allowance,Train{ //Field //Constructor Student(){} Student(String name, int age, int weight){ super(name, age, weight); } //Method public void in(int price, String name){System.out.printf("%s에게서 %d원 용돈을 받았습니다.%n",name,price);} public void out(int price, String name){System.out.printf("%d원 금액을 지출했습니다. 지출 용도 %s%n",price,name);} public void train(int training_pay, String name){System.out.printf("%s %d원 입금 완료%n",name,training_pay);} } public class Java100_oop_Interface3{ public static void main(String[] args){ // 객체 생성 Student s1 = news Student("홍길동",20,85); // 클래스와 인터페이스로부터 상속(Person)과 구현(Allowance, Train)을 한 메서드들 호출 s1.wash(); //씻다 s1.study(); //공부하다 s1.play(); //놀다 s1.in(10000,"엄마"); //엄마에게서 10000원 용돈을 받았습니다. s1.out(5000,"편의점"); //5000원 금액을 지출했습니다. 지출 용도 편의점 s1.train(50000,"아빠"); //아빠 50000원 입금 완료 // 상수 필드 사용하기 System.out.println(s1.aaa); System.out.println(Allowance.aaa); // 같은 값 출력 됨 } }
6. 다형성(polymorphism)에 대해서 개념 설명
[1] 다형성이란?
다형성이란 다양한 형태 또는 특성을 가진다는 의미
자바와 같은 객체 지향 언어에서의 의미는 부모 클래스를 상속받은 자식 클래스의 인스턴스가 부모의 객체로도 사용되고 뿐만 아니라 자식 클래스의 객체로도 사용될 수 있는 다양한 상황을 의미
[2] 예시
부모 클래스 Bird가 있고, 이를 상속받은 자식 클래스 Parrot이 있다고 가정
이때, "앵무새가 말을 하네" 이렇게 사람들이 말할 수 있다
그런데, 앵무새는 새기 때문에 "새가 말을 하네" 이렇게도 말할 수 있다
[3] 결론
정리하면, 하위 클래스의 인스턴스(객체)는 보다 위인 상위 클래스의 인스턴스(객체)로도 사용될 수 있다
그런데 그 반대는 안 된다
따라서, 상위(부모) 클래스의 인스턴스(객체)는 하위(자식) 클래스의 인스턴스(객체)로 사용될 수 없다
class Person{} class Student extends Person{} public class Java100_oop_Polymorphism2{ public static void main(String[] args){ // 1 객체 생성 Student s1 = news Student(); // 2 객체 생성 -> 부모 타입으로 Person s2 = new Student(); // 3 객체 생성 Person aaa = new Person(); // 4 객체 생성 -> 상위(부모) 클래스로 객체를 생성하면서 타입은 하위(자식) 타입을 쓰는 경우 Student bbb = new Person(); //Err } }
'개발자 수업 > 인터넷 강의' 카테고리의 다른 글
자바 100제 Part.4 / 1 ~ 7 (0) 2021.09.23 자바 100제 Part.3 / 24 ~ 28 (0) 2021.09.22 자바 100제 Part.3 / 5 ~ 13 (0) 2021.09.17 자바 100제 Part.3 / 1 ~ 4 (0) 2021.09.17 자바 100제 Part.2 / 13 ~ 24 (0) 2021.09.15