다형성(Polymorphism) - 김상호
다형성이란?
하나의 객체가 여러가지의 타입을 가질 수 있는 것
다형성은 상속, 추상화와 함께 객체 지향 프로그래밍에서 중요한 특징 중 하나이다.
Tv => 부모 타입, SmartTv => 자식 타입 일때
부모 타입 참조 변수로 자식 타입 객체를 다루는 것
ex)
Tv t = new SmartTv();
Plain Text
복사
단, 자식 타입의 참조변수로 부모 타입의 객체를 가리킬 수 없다.
Tv t = new SmartTv(); // 허용
SmartTv t = new Tv(); // 허용X
Plain Text
복사
•
참조 변수가 사용할 수 있는 멤버의 개수가 실제 인스턴스의 멤버 개수보다 많기 때문에 자식 클래스 타입의 참주 변수로는 부모 클래스 타입의 인스턴스를 참조 할 수 없다.
정리하자면
1.
같은 타입의 인스턴스 참조 (O)
2.
부모 -> 자식 인스턴스 참조 (O)
3.
자식 -> 부모 인스턴스 참조 (x)
•
클래스는 상속을 통해 확장, 유지는 가능하지만 축소는 되지 않기 때문에 자식 클래스에서 사용할 수 있는 멤버의 개수가 부모 클래스와 언제나 같거나 많다.
다형성을 사용하는 이유
유지보수가 쉽다.
•
여러 객체를 하나의 타입으로 관리 할 수 있기 때문에 코드 관리가 편해져 유지보수가 쉽다.
결합도 하락
•
클래스간의 의존성이 줄어들어 결합도가 낮아지고 독립성이 강해진다.
다형성 예제 코드
class MobilePhone {
protected String number;
public MobilePhone(String num) {
number = num;
}
public void answer() {
System.out.println("Hi~ from " + number);
}
}
class SmartPhone extends MobilePhone {
private String androidVer;
public SmartPhone(String num, String ver) {
super(num);
androidVer = ver;
}
public void playApp() {
System.out.println("App is running in " +
androidVer);
}
}
public class dkd {
public static void main(String[] args) {
SmartPhone ph1 =
new SmartPhone("010-555-777",
"Nougat");
MobilePhone ph2 =
new SmartPhone("010-999-333",
"Nougat");
ph1.answer();
ph1.playApp();
System.out.println();
ph2.answer();
// ph2.playApp();
}
}
Plain Text
복사
출력 결과
Hi~ from 010-555-777
App is running in Nougat
Hi~ from 010-999-333
Plain Text
복사
추상 클래스(Abstract Class) - 이가현
추상메서드 (abstract method)
•
메서드는 선언부와 구현부로 구성되어 있지만 추상메서드는 선언부만 작성
•
미완성 메서드
•
/* 주석을 통해서 어떤 기능을 수행할 목적으로 작성하였는지 설명한다.*/
•
abstract 리턴타입 메서드 이름();
•
추상클래스를 상속받는 자손클래스는 ‘오버라이딩’을 통해 추상클래스의 구현부를 모두 구현주어야한다.
public abstract 리턴타입 메서드 이름();
Java
복사
예제
public abstract class Shape {
int x,y;
public void translate(int x, int y) { // 추상클래스 안에 보통메서드 사용 가능
this.x = x;
this.y=y;
}
public abstract void draw();
}
class Rectangle extends Shape{
int width, height;
public void draw() {
System.out.println("사각형 그리기 메소드");
}//추상클래스의 추상메서드 draw를 오버라이딩하여 구현부 작성 후 abstract 삭제
}
class Circle extends Shape{
int radius;
public void draw() {
System.out.println("사각형 그리기 메소드");
}//추상클래스의 추상메서드 draw를 오버라이딩하여 구현부 작성 후 abstract 삭제
}
Java
복사
인터페이스(Interface) - 임학준
인터페이스
•
개발코드와 객체가 서로 통신하는 역활을한다
•
협업할때 인터페이스를 기반으로 한다
•
인터페이스 타입으로 사용함을 알려주기위해 implements키워드를 추가하고 인터페이스 이름을 명시해야 한다
•
interface로 생성된 메소드 앞에는 public abstract(생략가능 컴파일러 기본생성)이 들어간다
[public]interface 인터페이스 이름 { ... }
public class 구현클래스 이름 implements 인터페이스 이름{ ... }
//인터페이스에 선언된 추상 메소드의 실체 메소드 선언
Java
복사
interface Printable{
public abstract void print(String doc);//abstract붙으면 함수구현부{}가없다
}
class SprinterDriver implements Printable{//클래스 상속받을때는 extends
//implements는 interface의 상속
@Override
public void print(String doc) {
System.out.println("삼성 프린터 입니다.");
System.out.println(doc);
}
}
class LPrinterDriver implements Printable{
//abstract라 자손이 구현해야함
@Override
public void print(String doc) {
System.out.println("LG 프린터 입니다.");
System.out.println(doc);
}
}
public class DriverTest {
public static void main(String[] args) {
Printable prn = new SprinterDriver();//다형성
prn.print("출력해 주세요");
prn = new LPrinterDriver();
prn.print("출력해 주세요");
}//출력결과
}/*삼성 프린터 입니다.
출력해 주세요
LG 프린터 입니다.
출력해 주세요*/
Java
복사
다중상속(다중 인터페이스 구현 클래스)
•
자바는 다중상속이 지원되지 않는다 (프로그램 복잡도가 높아지기 때문)
•
다중상속을 하고싶으면 인터페이스를 사용한다(지원까지는 아니고 비슷하게 가능)
public class 구현클래스이름 implements 인터페이스A , 인터페이스B
Java
복사
interface Printable{//inter
public abstract void print(String doc);//abstract붙으면 함수구현부{}가없다
}
interface Drivable{
void drive();//기본적으로 public abstract을 컴파일러가 넣는다
}
interface Flyable{
void fly();
}
class FlyingCar implements Drivable,Flyable{//다중상속을 흉내
//인터페이스는 다중상속 클래스는 단일상속
@Override
public void fly() {
System.out.println("날수 있습니다");
}
@Override
public void drive() {
System.out.println("드라이브가 가능합니다:");
}
}
public class DriverTest {
public static void main(String[] args) {
FlyingCar flyingcar = new FlyingCar();
flyingcar.drive();
flyingcar.fly();
}//출력결과
}/*드라이브가 가능합니다:
날수 있습니다*/
Java
복사
디폴트 메소드
•
인터페이스 다음에는 추가함수,상수 가 온다
•
JDK 1.8부터 default로 일반함수(구현된 함수)도 구현 할 수 있게 되었다
인터페이스(Interface) - 최아영
인터페이스
interface 인터페이스명 {
추상 메소드
};
•
클래스들이 구현해야 하는 동작을 지정하는데 사용되는 추상 자료형이다.
•
다른 클래스를 작성하는데 도움 줄 목적으로 작성된다.
•
모든 필드는 public static final이어야 하며 이를 생략할 수 있다.
•
모든 메소드는 public abstract 이어야 하며 이를 생략할 수 있다.
(static 메소드와 default 메소드는 예외)
class 클래스명 implements 인터페이스명 {…};
•
자신에 정의된 추상 메서드의 구현체 만들어주는 클래스를 작성해야한다.
•
관련 없는 클래스들이 동일한 동작을 구현하기를 원할때 사용한다.
•
특정한 자료형의 동작을 지정하고 싶지만 누가 구형하든지 신경 쓸 필요가 없을 때 사용한다.
•
다중 상속이 필요할 때 사용한다.
interface Printable {
public abstract void print(String doc);
}
class SPrinterDriver implements Printable {
@Override
public void print(String doc) {
System.out.println("삼성 프린터 입니다.");
System.out.println(doc);
}
}
class LPrinterDriver implements Printable {
@Override
public void print(String doc) {
System.out.println("LG 프린터 입니다.");
System.out.println(doc);
}
}
public class PrinterTest {
public static void main(String[] args) {
Printable prn1 = new SPrinterDriver();
Printable prn2 = new LPrinterDriver();
prn1.print("출력해주세요.");
prn2.print("출력해주세요.");
}
}
Java
복사
다중상속
•
자바는 다중상속을 허용하지 않는다.
•
인터페이스를 이용하면 다중상속의 효과를 낼 수 있다.
interface Drivable {
void drive();
}
interface Flyable {
void fly();
}
// 다중 상속
class FlyingCar implements Drivable, Flyable {
@Override
public void drive() {
System.out.println("드라이브가 가능합니다.");
}
@Override
public void fly() {
System.out.println("날 수 있습니다.");
}
}
public class CarTest {
public static void main(String[] args) {
FlyingCar car = new FlyingCar();
car.drive();
car.fly();
}
}
Java
복사
디폴트 메소드
•
인터페이스에 메소드 구현이 가능하다.
•
메소드 앞에 default를 붙여야 한다.
interface Shape {
final double PI = 3.14;
public abstract void draw();
public abstract double getArea();
default public void redraw() {
System.out.println("--- 다시 그립니다..");
draw();
}
}
class Circle implements Shape {
private int radius;
public Circle (int radius) {
this.radius = radius;
}
@Override
public void draw() {
System.out.println("원을 그립니다.");
}
@Override
public double getArea() {
return radius * radius * PI;
}
@Override
public void redraw() {
Shape.super.redraw();
}
}
public class ShapeTest {
public static void main(String[] args) {
Shape donut = new Circle(10);
donut.redraw();
System.out.println("면적은 " + donut.getArea());
}
}
Java
복사
과제1(Selection Sort) - 조국현
public class SelectionSort {
public static void main(String[] args){
int[] arr = {7, 3, 2, 8, 9, 4, 6, 1, 5};
int min;
int temp, index=0;
for(int i = 0; i < arr.length-1; i++) {
min = arr[i];
for(int j = i+1; j < arr.length; j++) {
if(min > arr[j]) {
min = arr[j];
index = j;
}
}
temp = arr[i];
arr[i] = arr[index];
arr[index] = temp;
}
for (int num : arr) {
System.out.println(num);
}
}
}
JavaScript
복사
과제2(Stack Implement) - 김기헌
Stack을 Array 기반으로 구현하기
Main class → main 메소드
package _0927.stack;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int size = 0;
Scanner sc = new Scanner(System.in);
System.out.println("스택 사이즈 입력:");
size = sc.nextInt();
Stack stack = new Stack(size);
while (true) {
int num;
System.out.println("0: Stop 1: push 2: pop 3: peek 4: number of stack member 5: isEmpty 6: clear");
num = sc.nextInt();
if (num == 0) {
System.out.println("종료되었습니다");
break;
}
Action action = new Action(num, stack);
action.exe();
stack.printStack();
}
}
}
Java
복사
Function Interface
package _0927.stack;
public interface Function {
boolean isEmpty();
void push(char input);
void clear();
void pop();
void peek();
void number();
void printStack();
}
Java
복사
Stack Class → 스택 기능들을 구현한 클래스
package _0927.stack;
public class Stack implements Function {
private int size, top = -1;
private char arrayStack[];
public Stack(int size) {
this.size = size;
this.arrayStack = new char[size];
}
@Override
public boolean isEmpty() {
if (top == -1) return true;
else return false;
}
@Override
public void push(char input) {
if (top < size - 1) {
arrayStack[top + 1] = input;
top++;
System.out.println(input + "값을 스택에 넣었습니다");
} else {
System.out.println("스택이 가득 찼습니다");
}
}
@Override
public void clear() {
if (!isEmpty()) {
arrayStack = new char[this.size];
top = -1;
System.out.println("스택 클리어 완료");
} else {
System.out.println("스택이 이미 비어있습니다");
}
}
@Override
public void pop() {
if (!isEmpty()) {
char tmp = arrayStack[top];
top--;
System.out.println(tmp + " 제거 완료");
} else {
System.out.println("스택이 비어 있습니다");
}
}
@Override
public void peek() {
if (!isEmpty()) {
System.out.println("현재 스택의 top: " + arrayStack[top]);
} else {
System.out.println("스택이 비어 있습니다");
}
}
@Override
public void printStack() {
if (isEmpty()) {
System.out.println("Stack is empty");
} else {
System.out.printf("현재 스택에는 ");
for (int i = 0; i < top + 1; i++) {
System.out.printf("%c ", arrayStack[i]);
}
System.out.println("가 있습니다");
}
}
@Override
public void number(){
System.out.println("현재 스택에는 "+(top+1)+"개의 멤버가 있습니다");
}
}
Java
복사
Action Class → 어떤 기능을 수행할지 전달 받아 기능을 수행하는 클래스
package _0927.stack;
import java.util.Scanner;
public class Action {
private int num;
private Stack stack;
public Action(int num, Stack stack) {
this.num = num;
this.stack = stack;
}
public void exe() {
switch (num) {
case 0:
break;
case 1:
char input;
Scanner sc = new Scanner(System.in);
System.out.println("입력 값:");
input = sc.next().charAt(0);
stack.push(input);
break;
case 2:
stack.pop();
break;
case 3:
stack.peek();
break;
case 4:
stack.number();
break;
case 5:
stack.isEmpty();
break;
case 6:
stack.clear();
break;
}
}
}
Java
복사