8.Java 오버라이딩/super/다형성/toString/추상클래스
2022.07.13.수
1)오버라이딩(overriding)
-개념 : 부모 클래스의 메서드를 자식 클래스가 재정의 가능한 방법으로서 자식에서 수정된 메서드를 의미
-규칙 : 부모클래스 메서드의 리턴타입, 메서드명, 파라미터 동일해야함, 접근지정자는 같거나 확대가능
public class Pet
{
//공통적인 속성
public String name;
public int age;
//공통적인 동작
public void eat()
{
System.out.println("eat");
}
public void sleep()
{
System.out.println("sleep");
}
public Pet() {}
public Pet(String name, int age)
{
this.name = name;
this.age = 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;
}
}
public class Cat extends Pet
{
//의존적인 속성
String gender;
//의존적인 동작
public void cry()
{
System.out.println("Cat.cryCat");
}
//재정의
@Override //어노테이션
public void eat()
{
System.out.println("냠냠");
}
@Override
public void sleep()
{
System.out.println("쿨쿨");
}
public Cat() {}
public Cat(String name, int age, String gender)
{
super(name, age);
this.gender = gender;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
public class Dog extends Pet
{
//의존적인 속성
String color;
//의존적인 동작
public void swim()
{
System.out.println("Dog.swimDog");
}
//재정의
@Override //어노테이션
public void eat()
{
System.out.println("쩝쩝");
}
@Override
public void sleep()
{
System.out.println("드르렁");
}
public Dog() {}
public Dog(String name, int age, String color)
{
super(name, age);
this.color = color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
public class TestPet {
public static void main(String[] args)
{
Cat c = new Cat("야옹이1", 2, "암컷");
Cat c2 = new Cat("야옹이2", 2, "수컷");
//기능호출
c.eat();
c.sleep();
c.cry();
Dog d = new Dog("멍멍이1", 3, "화이트");
Dog d2 = new Dog("멍멍이2", 3, "블랙");
//기능호출
d.eat();
d.sleep();
d.swim();
}
}
2)super 키워드
public class Pet
{
String name;
int age;
public Pet() {}
public Pet(String name, int age)
{
this.name = name;
this.age = age;
}
//name, age 한꺼번에 반환해주는 메서드
public String getInfo()
{
return name + "\t" + age;
}
//오버로딩
public String getInfo(int n)
{
return null;
}
}
public class Cat extends Pet
{
//추가적인 속성
String gender;
public Cat() {}
public Cat(String name, int age, String gender)
{
super(name, age);
this.gender = gender;
}
@Override
public String getInfo()
{
//=return name + "\t" + age + "\t" + gender;
return super.getInfo() + "\t" + gender;
}
}
3)다형성(polymorphism)
-개념 : 상속이 전제되어 있을 때 큰 타입의 참조 변수가 같거나 작은타입을 참조할 수 있는 능력
-문법 : 부모타입 변수 = new 작은타입();
-장점 : 재사용성
-참고사항 : 가)하위 클래스에서 추가된 멤버는 접근 불가 -> 형변환으로 해결
나)특정 타입 instanceof 연산자로 추론가능
-활용 : 가)배열
나)메서드 파라미터 변수
public class Cat extends Pet
{
//추가적인 속성
String gender;
public Cat() {}
public Cat(String name, int age, String gender)
{
super(name, age);
this.gender = gender;
}
@Override
public String getInfo()
{
//=return name + "\t" + age + "\t" + gender;
return super.getInfo() + "\t" + gender;
}
}
public class TestPet2 {
public static void main(String[] args)
{
//1.일반적인 객체 생성 방법 ==> 변수갯수 많아짐
Pet p = new Pet("앵무새", 2);
Cat c = new Cat("야옹이1", 2, "암컷");
Dog d = new Dog("멍멍이1", 3, "화이트");
//2.다형성 ==> 변수 하나로 다양한 객체 관리 가능 -> 재사용성 증가
Pet p2 = new Pet("앵무새", 2);
System.out.printf("이름:%s, 나이:%d \n", p2.getName(), p2.getAge());
p2 = new Cat("야옹이1", 2, "암컷");
//자식에서 추가된 멤버(변수, 메서드)를 참조하기 위해서는 자식타입으로 형변환 해야함
//Cat c2 = (Cat)p2;
//System.out.printf("이름:%s, 나이:%d, 성별:%s", c2.getName(), c2.getAge(), c2.getGender());
System.out.printf("이름:%s, 나이:%d, 성별:%s \n", p2.getName(), p2.getAge(), ((Cat)p2).getGender());
p2 = new Dog("멍멍이1", 3, "화이트");
System.out.printf("이름:%s, 나이:%d, 성별:%s \n", p2.getName(), p2.getAge(), ((Dog)p2).getColor());
}
}
public class TestPet3_배열활용 {
public static void main(String[] args)
{
/*
1.다형성 활용 ==> 배열 이용
고양이 10마리, 강아지 20마리
1)개별적으로 객체 생성 저장 ==> 변수30개 필요
2)개별타입으로 배열 생성 ==> 변수2개 필요
3)다형성 ==> 변수1개 필요
*/
Pet[] pets = { new Cat("야옹이1", 2, "암컷"),
new Dog("멍멍이1", 3, "화이트"),
new Cat("야옹이2", 3, "수컷"),
new Dog("멍멍이2", 2, "블랙"),
new Cat("야옹이3", 1, "암컷") };
for(Pet i : pets)
{
//고양이? 강아지? ==> instanceof 연산자 이용해서 원래 타입을 식별 할 수 있음
//문법 : 변수명 instanceof클래스
if(i instanceof Cat)
{
System.out.printf("이름:%s, 나이:%d, 성별:%s \n", i.getName(), i.getAge(), ((Cat)i).getGender());
}
else
{
System.out.printf("이름:%s, 나이:%d, 색상:%s \n", i.getName(), i.getAge(), ((Dog)i).getColor());
}
}
}
}
public class TestPet4_메서드활용 {
//정보출력하는 메서드
public static void info_print(Pet pet)
{
System.out.printf("이름:%s, 나이:%d", pet.getName(), pet.getAge());
if(pet instanceof Cat)
{
System.out.printf(", 성별:%s", ((Cat)pet).getGender());
}
else if(pet instanceof Dog)
{
System.out.printf(", 색상:%s", ((Dog)pet).getColor());
}
else if(pet instanceof Pet) //istanceof 사용시 상속구조에서 부모타입을 가장 마지막에 비교해야함
{
}
System.out.println();
}
public static void main(String[] args)
{
//2.다형성 활용 ==> 메서드 파라미터 변수
Pet p = new Pet("앵무새", 2);
Cat c = new Cat("야옹이1", 2, "암컷");
Dog d = new Dog("멍멍이1", 3, "화이트");
info_print(p);
info_print(c);
info_print(d);
System.out.println(p.toString());
}
}
3)Object 클래스 toString() 메서드
-반환값 : 클래스명@16진수
-Object 클래스의 toString() 메서드를 하위 클래스에서 재정의해서 사용해야함
-toString : 참조변수를 출력할 때 자동 호출됨
==>sysout(참조형 변수) = sysout(참조형 변수.toString())
/*
재사용 클래스 작성 패턴
1.인스턴스 변수
2.생성자
3.getter/setter
4.toString() 재정의
*/
public class Student //extends Object가 자동 지정됨
{
String name;
int age;
public Student() {}
public Student(String name, int age) {
this.name = name;
this.age = 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;
}
@Override
public String toString()
{
return "Student [name=" + name + ", age=" + age + "]";
}
}
public class TestStudent {
public static void main(String[] args)
{
Student s = new Student("홍길동", 20);
//기존방식
System.out.println(s.getName() + "\t" + s.getAge());
//참조 변수 출력
System.out.println(s);
System.out.println(s.toString());
}
}
4)추상클래스
-public abstract class 클래스명 {}
-구성요소 : 변수, 메서드, 생성자, 추상메서드
-추상메서드를 가지면 반드시 추상클래스로 만들어야 함(※추상 클래스가 반드시 추상 메서드를 가질 필요는 없음)
-객체 생성 불가(불완전한 클래스)
-추상메서드(불완전한 메서드) : public abstract void a(); (기능이 구현 되지 않음)
-다른 클래스(concrete class)의 도움을 받아(상속) 추상클래스를 사용할 수 있음
-자식 클래스(추상화 클래스 상속)에서 추상메서드를 재정의(overriding)해서 사용할 수 있음
-목적 : 반드시 추상 클래스의 추상 메서드로 구현하도록 강제
가) 추상화 하지 않은 클래스
package com.unabstract;
public class Pet
{
//변수
//생성자
//메서드
//공통적인 기능
public void eat()
{
System.out.println("eat");
}
}
package com.unabstract;
public class Cat extends Pet
{
//변수
//생성자
//메서드
//재정의 안하고 자기 멋대로 메서드 추가
public void eatCat()
{
System.out.println("냠냠");
}
}
package com.unabstract;
public class Dog extends Pet
{
//변수
//생성자
//메서드
//재정의 안하고 자기 멋대로 메서드 추가
public void eatDog()
{
System.out.println("쩝쩝");
}
}
package com.unabstract;
public class TestPet {
public static void main(String[] args)
{
Cat c = new Cat();
c.eatCat();
Dog d = new Dog();
d.eatDog();
}
}
나)추상클래스
package com.abstract2;
public abstract class Pet
{
//변수
String name;
//생성자
Pet() {}
//메서드
public String getName() { return name; }
//추상메서드
//추상메서드 반드시 재정의 해야함
public abstract void eat();
}
package com.abstract2;
public class Cat extends Pet
{
@Override
public void eat()
{
System.out.println("냠냠");
}
}
package com.abstract2;
public class Dog extends Pet {
@Override
public void eat()
{
System.out.println("쩝쩝");
}
}
package com.abstract2;
public class TestPet {
public static void main(String[] args)
{
// Pet p = new Pet(); //추상클래스 new 불가
//다형성 가능
Pet p = new Cat();
Pet p = new Dog();
Cat c = new Cat();
c.eat();
Dog d = new Dog();
d.eat();
//eat으로 메서드 일치
}
}