# 17. Java 16일차(230905) [국비교육]

brand_mins·2023년 9월 5일

Java

목록 보기
17/47

1. 싱글톤 패턴

  • 인스턴스 하나만 생성할 수 있는 클래스

2. 상속

(1) 상속

  • 기존 클래스의 기능을 그대로 사용하면서 새로운 기능이 추가된 클래스를 만들고 싶을때 사용함.
- Child 클래스는 Parent클래스를 extends로 상속받는 예제
class Parent {
	public void print() {
    	System.out.println("I am the parent.");
        }
}

class Child extends Parent { }

public class Main {
	public static void main(String[] args) {
    	Child child = new Child();
        child.print();
    }
}
  • 부모에 있는 메소드를 자식이 재정의하면 자식 클래스의 인스턴스는 재정의된 메소드가 출력
  • 즉, 우리는 그것을 메소드 오버라이딩이라고 한다.
class Animal {
	private String name = "";
   	
    public Animal(String name) {
    	this.name = name;
    }
    
    public String getName() {
    	return name;
    }
    
    public void speak() {
    	System.out.println("The animal speaks");
    }
}

class Dog extends Animal {
	public Dog(String name) {
    	super(name); // 부모클래스를 상속받는 메소드
    }
    @Override // 메소드 재정의
    public void speak() {
    	System.out.println("The dog barks");
    }
}

public class Main {
	public static void main(String[] args) {
    	Animal animal = new Animal("Animal");
        System.out.println(animal.getName());
        animal.speak();
        
        Dog dog = new Dog("Dog");
        // 부모 클래스에만 있는 메소드
        System.out.println(dog.getName());
        dog.speak(); // 부모 클래스에 있는 메소드
        }
}
- super을 이용해서 부모 생성자 접근.
class Person {
	private String name = "";
    private int age = 0;
    
    public Person(String name, int age) {
    	this.name = name;
        this.age = age;
    }
    
    public String getName() {
    	return name;
    }
    
    public int getAge() {
    	return age;
    }
    
    public void introduce() {
    	System.out.println("name: " + name + ", age: " + age);
    }
}

class Student extends Person {
	private int grade = 0;
    
    public Student(String name, int age, int grade) {
   		super(name,age);
        this.grade = grade;
    }
    
    public int getGrade() {
    	return grade;
    }
    
    public void study() {
    	System.out.println("I am studying");
    }
}

class Teacher extends Person {
	private String subject = "";
    
    public Teacher(String name, int age, String subject) {
    	super(name,age);
        this.subject = subject;
    }
    
    public String getSubject() {
    	return subject;
    }
    
    public void teach() {
    	System.out.println("I am teaching");
    }
}

public class Main {
	public staic void main(String[] args) {
    	Person person = new Person("John", 30);
        person.introduce();
        
        Student student = new Student("John", 20, 3);
        student.introduce();
        student.study();
        
        Teacher teacher = new Teacher("Smith", 40, "Math");
        teacher.introduce();
        teacher.teach();
    	}
}
- p.325) 상속을 이용하여 사각형의 넓이, 부피를 구현하시오.
class Rectangle() {
	public double width = 1;
    public double depth = 1;
    
    public double area() {
    	return width * depth;
    }
    
    public Rectangle() { }
    public Rectangle(double width) {
    	this(width,width);
    }
    
    public Rectangle(double width, double depth) {
    	super();
        this.width = width;
        this.depth = depth;
    }
}

class RectanglePillar extends Rectangle {
	public double height = 0;
    public double volume() {
    	return area() * height;
    }
    
    public RectanglePillar() { }
    public RectanglePillar(double width, double depth, double height) {
    	super(width, depth);
        this.height = height;
    }
}

public class JavaEx01 {
	public static void main(String[] args) {
    	Rectangle r = new Rectangle(5);
        System.out.println("사각형의 넓이: " + r.area());
        
        RectanglePillar rp = new RectanglePillar(3,4,5);
        System.out.println("사각형의 넓이: " + rp.area());
        System.out.println("사각형의 부피: " + rp.volume());
      }
}

3. 오버라이드

  • 부모의 메소드를 자식의 메소드에서 재정의함
public class Animal {
	public void move() {
    	System.out.println("동물이 움직입니다.");
   	}
}
public class Dog extends Animal {
	@Override
    public void move() {
    	System.out.println("강아지가 네 발로 걸어다닙니다");
    }
}

public class Cat extends Animal {
	@Override
    public void move() {
    	System.out.println("고양이가 네 발로 걸어다닙니다");
    }
}

public class Main {
	public static void main(String[] args) {
    	Animal animal1 = new Animal();
        Dog dog2 = new Dog();
        Cat cat3 = new Cat();
        animal1.move();
        dog2.move();
        cat3.move();
    }
}
++ 면접에서 잘 물어봄 ++
오버로딩: 메소드명은 같지만 매개변수가 서로 다를때 식별가능한 것
오버라이딩: 부모클래스의 메소드를 자식클래스의 이름을 같게하여 재정의함.

4. 다형성

  • 하나의 클래스 변수에 다양한 클래스를 넣는 것
  • 상속을 통해서 부모 자식 클래스가 만들어지면 부모 클래스 변수를 자식 클래스에 넣을 수 있음.
//Animal클래스
public class Animal {
	public void makeSound() {
    	System.out.println("동물이 소리를 냅니다");
    }
}

// Dog 클래스
public class Dog extends Animal {
	@Override
    public void makeSound() {
    	System.out.println("멍멍!");
    }
}

// Cat 클래스
public class Cat extends Animal {
	@Override
    public void makeSound() {
    	System.out.println("야옹~");
    }
}

// Main 클래스
public class Main {
	public static void main(String[] args) {
    	// 변수를 사용한 다형성
        Animal animal1 = new Dog();
        Animal animal2 = new Cat();
        Animal animal3 = new Animal();
        
        animal1.makeSound();
        animal2.makeSound();
        animal3.makeSound();
        
        // array를 이용한 다형성
        Animal[] animals = new Animal[3];
        animals[0] = new Dog();
        animals[1] = new Cat();
        animals[2] = new Animal();
        
        for(Animal animal : animals) {
        	animal.makeSound();
        }
        
        // ArrayList를 이용한 다형성
        Animal a1 = new Dog();
        Animal a2 = new Cat();
        Animal a3 = new Animal();
        ArrayList<Animal> animals = new ArrayList<>();
        // 메소드를 이용해서 계산할때 add사용
        animals.add(a1);
        animals.add(a2);
        animals.add(a3);
        
        for (Animal animal : animals) {
        	animal.makeSound();
        }
    }
}
=========================================
<예시: 또 다른 예시>
class Shape {
	void drow1() {
		System.out.println("Shape:drow1");
	}
	
	void drow2() {
		System.out.println("Shape:drow2");
	}
}

class Triangle extends Shape {
	@Override
	void drow2() {
		System.out.println("Triangle-drow2");
	}	
	void drow3() {
		System.out.println("Triangle-drow3");
	}
}


public class JavaEx02 {

	public static void main(String[] args) {
		System.out.println("Shape에 Shape를 넣어 출력------------------------");
		Shape s1 = new Shape();
		s1.drow1();
		s1.drow2();
		System.out.println("s1.drow3() Shape에 없는 메소드여서 접근 불가");
		
		System.out.println("Triangle에 Triangle(자식)를 넣어 출력 -------------");
		Triangle t1 = new Triangle();
		t1.drow1();
		t1.drow2();
		t1.drow3();
		
		// Triangle 자식 클래스가 Shape 부모 클래스로 넣을 수 없음.
		System.out.println("Shape(부모)에 Triangle(자식)을 넣어 출력------------");
		Shape s2 = new Triangle(); // 부모에 자식클래스 넣을 수 있음(다형성)
		s2.drow1(); // s2는 Shape 부모이지만 들어있는 것이 자식이여서 다형성을 위해 drow2 출력
		s2.drow2();
		//s2.drow3()를 출력하고 싶다면 원래의 모양으로 강제형변환해야함.
		Triangle t2 = (Triangle)s2;
		t2.drow3();
	}

}
1. 또 다른 예
class Pet {
	public void eat() {
		System.out.println("Pet이 밥을 먹는다.");
	}
	public void move() {
		System.out.println("Pet이 움직인다.");
	}
}

class Cat extends Pet {
	@Override
	public void eat() {
		System.out.println("Cat이 밥을 먹는다.");
	}
	public void work() {
		System.out.println("고양이가 쥐를 잡는다.");
	}
}

class Dog extends Pet {
	@Override
	public void eat() {
		System.out.println("Dog가 뼈다귀를 먹는다. 육식");
	}
	public void hunting() {
		System.out.println("Dog가 꿩을 사냥한다.");
	}
}


public class JavaEx03 {

	public static void main(String[] args) {
		Pet a0 = new Pet();
		Pet a1 = new Cat();
		Pet a2 = new Dog();
		
		a0.eat();
		a1.eat();
		a2.eat();

	}
}
- 배열을 이용한 다형성
class Student {
	// 학생관련 여러 메소드 생략
	public void information() {
		System.out.println("학생의 정보를 출력");
	};
}

class HSchoolStudent extends Student {
	public void information() {
		System.out.println("고등학생의 정보를 출력");
		System.out.println("원하는 진로정보 출력");
	};
}

class UniversityStudent extends Student {
	public void information() {
		System.out.println("대학생의 정보를 출력");
		System.out.println("원하는 취업처 정보 출력");
	}
}

public class JavaEx04 {

	public static void main(String[] args) {
		// 부모인 Student 클래스에 다형성을 이용해서 Student와 관련된 클래스들을 넣을 수 있음.
		Student[] sts = {
				new Student(), new HSchoolStudent(), new UniversityStudent()				
		};
		
		// 학생 클래스와 관련된 모든 인스턴스와 information() 메소드를 실행
		for(Student st : sts) {
			System.out.println("---------------------------");
			st.information();
		}

	}

}

(1) 다형성 예제

- 9/5 기준 실습용도로 학습
- 9/6 기준 복습하기
1. 제품 종류로 TV, 컴퓨터가 있음. 제품마다 5% 10% 할인
TV에는 inch, 컴퓨터에는 RAM크기와 같은 특별한 속성
두 제품 다 최종가격을 리턴하는 getPrice 메소드
TV의 경우 10인치가 넘어가면 가격에 배송료 만원 추가
RAM 같은 경우 1GB당 2만원을 가격에 추가

1] 부모 클래스로 Product 클래스를 만들어서 모든 제품이 가지고 있는 필드와 메소드를 구현하자.
class Product {
	public String id = "";
    public double price = 0;
    public double discountRate = 0;
    
    public Product(String id, double price, double discountRate) {
    	this.id = id;
        this.price = price;
        this.discountRate = discountRate;
    }
    
    public double getPrice() {
    	// 연산순서: 괄호 > 곱셈 > 뺄셈
    	return price-price * (discountRate/100);
    }
}

2] TV제품만 있는 필드와 TV에만 적용되는 계산 방법을 이용해서 TV클래스를 만들었다.
가격 계산 방법이 달라 getPrice 재정의함.
class TV extends Product {
	public double inch = 0;
    public TV(String id, double price, double discountRate, double inch) {
    	super(id,price,discountRate);
        this.inch = inch;
    }
    @Override
    public void getPrice() {
    	return inch > 10 ? super.getPrice+10000 : super.getPrice
    }
}

3] Computer 제품만 있는 필드와 Computer에만 적용되는 계산 방법을 이용해서 Computer 클래스 만듬
가격 계산 방법이 달라 getPrice 재정의
class Computer extends Product {
	public double Ram = 0;
    public Computer(String id, double price, double discountRate, double Ram) {
    	super(id,price,discountRate);
        this.Ram = Ram;
    }
    @Override
    public void getPrice() {
    	return super.getPrice+Ram*2;
    }
}

2. 고객은 VIP고객과 일반고객이 있음. 
VIP고객은 구매 요금 2%, 일반고객은 구매요금에 1% 포인트 적립.
VIP고객만 특별히 제품가격 5% 할인.
포인트는 모든 물건 할인 후 최종 결제 금액으로 포인트 추가
정보를 출력할 수 있도록 toString 구현

1] 일반 고객을 표현할 수 있는 Customer 클래스 만들기
아이디, 보유 포인트, 물건 구매시 포인트 취득비율을 넣을 수 있는 필드와
point를 구하는 setPoint 메소드를 가지고 있음.
class Customer {
	public String id = "";
    public int point = 0;
    public double pointRate = 0;
    
    public void setPoint(Product p) {
    	this.point = (int) (p.getPrice() * (pointRate/100));
    
    public Customer(String id, int point, double pointRate) {
    	this.id = id;
        this.point = point;
        this.pointRate = pointRate;
    }
    @Override
    public String toString() {
    	return "Customer [id = " + id + ", point=" + point + ", pointRate=" + pointRate + "]";
    }
}

2] VIP고객을 표현할 수 있는 VIPCustomer 클래스 만들기.
아이디, 보유 포인트, 물건 구매시 포인트 취득비율을 넣을 수 있는 필드와
point를 구하는 setPoint 메소드 가짐
class VIPCustomer extends Customer {
	public double priceRate = 0;
    
    public VIPCustomer(String id, int point, double pointRate, double priceRate) {
    	super(id,point,pointRate);
        this.priceRate = priceRate;
    }
    
    public void setPoint(Product p) { // 제품 p에 대한 point 적립
    	double resultPrice = p.getPrice() - (p.getPrice() * (priceRate / 100));
        this.point += (int) (resultPrice * (pointRate / 100);
    }
    
    @Override
    public String toString() {
    	return "VIPCustomer [priceRate =" + priceRate + ", id=" + id + ", point=" + point + ", pointRate=" + pointRate + "]";
    }
    	

3] 특정 고객이 특정 제품을 구매할때 고객의 포인트를 추가할 수 있도록 메인 클래스에 다음 프로그램을 넣어 완성하기.
public class Main {
	public static void main(String[] args) {
    	Product p1 = new TV("LG0015", 100000,10,40);
        Product p2 = new Computer("AMD0051", 100000, 20, 16);
        Customer c1 = new Customer("hong", 0, 1);
        Customer c2 = new VIPCustomer("kim",0,2,5);
        c1.setPoint(p1);
        c2.setPoint(p2);
        System.out.println(c1);
        System.out.println(c2);
}

4] 상위와 같은 형태의 관계 클래스들을 만들어 본인이 생각하는 기능을 추가하여 프로그램 구현
a) 부모: Vehicle 자식: Car, Bus
class Vehicle {
	public String transport = "";
    public int price = 0;
    
    public Vehicle(String transport, int price) {
    	this.transport = transport;
        this.price = price;
    }
    
    public void run() {
    	System.out.println("Vehicle이 움직이고 있습니다.");
    }
}
class Car extends Vehicle {
	public int speed = 0;
    
    public Car(String transport, int price, int speed) {
    	super(transport, price);
        this.speed = speed;
    }
    
    public void setSpeedUp() {
    	speed = speed + 10;
    }
    
    public void setSpeedDown() {
    	speed = speed - 10;
    }
    
    @Override
    public void run() {
    	System.out.println("Car가 움직이고 있습니다");
    }
}

class Bus extends Vehicle {
	public double distance = 0;
    
    public Bus(String transport, int price, double distance) {
    	super(transport, price);
        this.distance = distance;
    }
    
    public void setDistance() {
    	distance = distance + 10;
    }
    
    @Override
    public void run() {
    	System.out.println("Bus가 움직이고 있습니다");
    }
}

public class Main {
	public static void main(String[] args) {
    	Vehicle v1 = new Bus("천안버스",1500,30.0);
        Vehicle v2 = new Car("소나타", 0, 100);
        Vehicle v3 = new Vehicle("Vehicle",0);
        v1.run();
        v2.run();
        v3.run();
    }
}
b) 부모: Shape, 자식: Rectangle, Circle
class Shape {
	public String name;
    
    public Shape(String name) {
    	this.name = name;
    }
    
    public void draw() {
    	System.out.println("Shape를 그립니다");
   	}
}

class Rectangle2 extends Shape {
    public Rectangle2(String name) {
    	super(name);
    }
    
    @Override
    public void draw() {
    	System.out.println("사각형을 그립니다");
    }
}

class Circle2 extends Shape {    
    public Circle2(String name) {
    	super(name);
    }
    
    @Override
    public void draw() {
    	System.out.println("원을 그립니다");
    }
}


public class ClassEx08 {

	public static void main(String[] args) {
		Shape s1 = new Rectangle2("모양");
        Shape s2 = new Circle2("사각형");
        Shape s3 = new Shape("원");
        s1.draw();
        s2.draw();
        s3.draw();

	}

}
profile
IT 개발자가 되기 위한 기록

0개의 댓글