네이버 클라우드 부트캠프/복습 정리

7일차 Java [ 상속, 객체배열 ] ☆★

유정♡ 2024. 2. 28. 12:43

[ 상속 ]

상속 ( Inheritance ) 은 부모가 자식에게 물려주는 행위를 말한다. 객체 지향 프로그램에서도 부모 클래스의 필드와 메소드를 자식 클래스에게 물려줄 수 있다. 상속은 이미 잘 개발된 클래스를 재사용해서 새로운 클래스를 만들기 때문에 중복되는 코드를 줄여 개발 시간을 단축시킨다. 예를들어 자식클래스(B)에서 처음부터 필드와 메소드 4개를 작성하는 것보다는 field1과 method1을 부모클래스(A)에서 상속받고 있는 field2와 method2만 추가 작성하는 것이 효율적이다. 상속의 또다른 이점은 클래스의 수정을 최소화할 수 있다는 것이다. 부모 클래스를 수정하면 모든 자식 클래스에 수정 효과를 가져온다. 예를 들어 B,C가 A를 상속할 경우 A의 필드와 메소드를 수정하면 B,C를 수정하지 않아도 수정된 A의 필드와 메소드를 이용할 수 있다.

public class A {
   int field1;
   void method1() { ... }
}

public class B extends A {    //   => 자식 클래스 B에서 부모 클래스 A를 상속 
   String field2;
   void method2() { ... }
}

 

실제로 B클래스를 객체 생성해서 다음과 같이 사용할때에는 마치 B가 field1과 method1을 가지고 있는 것 처럼 보인다. 

B b = new B () ;    // => A로부터 물려받은 필드와 메소드
b.field1 = 10;
b.method1();

b.field2 = "홍길동";  // => B를 추가한 필드와 메소드
method2() ;

 

※ 클래스 상속 : 현실에서 상속은 부모가 자식을 선택해서 물려주지만, 프로그램에서는 자식이 부모를 선택한다. 자식 클래스를 선언할 때 어떤 부모로부터 상속받을 것인지를 결정하고, 부모 클래스를 다음과 같이 extends 뒤에 기술한다. 다른 언어와 달리 자바는 다중 상속을 허용하지 않는다. ( extend에서만 허용 안 함. 나중에 인터페이스(?) 에서는 허용 가능 )즉, 여러 개의 부모 클래스를 상속할 수 없다. 따라서 extends 뒤에는 단 하나의 부모 클래스만이 와야 한다.

public class 자식클래스 extends 부모클래스 {
}  

public class 자식클래스 extends 부모클래스1 , 부모클래스2 {
} => 부모클래스 2개는 못함.

 

※ 부모 생성자 호출 ☆★ : 현실에 부모 없는 자식이 있을 수도 없듯이 자바에서도 자식 객체를 생성하면 부모 객체가 먼저 생성된 다음에 자식 객체가 생성된다. 다음 코드는 Smartphone 객체만 생성되는 것처럼 보이지만, 사실은 부모 Phone 객체가 먼저 생성되고 그 다음에 자식인 SmartPhone 객체가 생성된 것이다. 

자식 클래스 변수 = new 자식 클래스 () ;

 

모든 객체는 생성자를 호출해야만 생성된다. 부모 객체도 예외는 아니다. 그렇다면 부모 객체의 생성자는 어디서 호출된 것일까? 이것에 대한 비밀은 자식 생성자에 숨어 있다. 부모생성자는 자식 생성자의 맨 첫 줄에 숨겨져있는 super() 에 의해 호출된다. super()는 컴파일 과정에서 자동 추가 되는데, 이것은 부모의 기본 생성자를 호출한다. 만약 부모 클래스에 기본 생성자가 없다면 자식 생성자 선언에서 컴파일 에러가 발생한다. 부모 클래스에 기본 생성자가 없고 매개변수를 갖는 생성자만 있다면 개발자는 다음과 같이 super(매개값,...) 코드를 직접 넣어야 한다. 이 코드는 매개값의 타입과 개수가 일치하는 부모 생성자를 호출한다.

public 자식 클래스 ( ... ) {     // 자식 생성자 선언
    super( );
     ...
}

public 자식 클래스 ( ... ) {      // 자식 생성자 선언
    super(매개값, ... );            // 부모 클래스에 기본 생성자가 없고 매개변수를 갖는 생성자만 있다면 개발자는
     ...                                         다음과 같이 super(매개값, ...) 코드를 직접 넣어야 한다.

}

상속 ( 1 )
상속 ( 2 )
상속 ( 2 - 1 ) => p.show(); 는 에러 왜냐햐면 show는 자식에만 있어서 부모로는 불러올 수 없음. s.show()만 가능 => s.name="lala"; 는 에러 왜냐 생성자 안에 들어간 name은 사용가능하나 직접적인 필드에 있는 name은 private이기 때문에 외부에서 접근 불가
상속 ( 3 ) - 출력되는 순서 맞추기


 

[ 메소드의 재정의 ]

상속에 나오는 개념. 부모 클래스의 모든 메소드가 자식 클래스에게 맞게 설계되어 있다면 가장 이상적인 상속이지만, 어떤 메소드는 자식 클래스가 사용하기에 적합하지 않을 수 있다. 이러한 메소드는 자식 클래스에서 재정의해서 사용해야 한다. 이것을 메소드의 오버라이딩 ( Overriding )이라고 한다. 

 

메소드 오버라이딩 ☆★ : 메소드 오버라이딩은 상속된 메소드를 자식 클래스에서 재정의하는 것을 말한다. 메소드가 오버라이딩 되었다면 해당 부모 메소드는 숨겨지고, 자식 메소드가 우선적으로 사용된다. 자바는 개발자의 실수를 줄여주기 위해 정확히 오버라이딩 되었는지 체크해주는 @Override 어노테이션을 제공한다. @Override를 붙이면 컴파일 단계에서 정확히 오버라이딩 되었는지 체크하고, 문제가 없다면 컴파일 에러를 출력한다.

 

오버라이딩 vs 오버로딩 차이 ※

    - 오버라이딩은 메소드이름 매개변수 등을 그대로 들고와서 재정의 하는 것. 자식 메소드가 우선 적용 됨.

    - 메소드 오버로딩은 메소드 이름은 같되 매개변수 타입,개수,순서가 다른 메소드를 여러개 언선하는 것. 

 

※ 오버라이딩 메소드 자동 생성 기능

          : Source -> Override/Implement Methods -> 부모 클래스에서 오버라이딩 될 메소드를 선택하고 -> OK 클릭 

메소드를 오버라이딩할 때는 다음과 같은 규칙에 주의해서 작성해야 한다.
    1) 부모 메소드의 선언부 ( 리턴 타입, 메소드 이름, 매개변수 )와 동일해야 한다.
    2) 접근 제한을 더 강하게 오버라이딩할 수 없다. ( public -> private 으로 변경 불가 )
    3) 새로운 예외를 throws할 수 없다.

메소드의 오버라이딩과 오버로딩의 차이점

 

 

※ 부모 메소드 호출 : 메소드를 재정의하면, 부모 메소드는 숨겨지고 자식 메소드만 사용되기 때문에 비록 부모 메소드 일부만 변경된다 하더라고 중복된 내용을 자식 메소드도 가지고 있어야 한다. 예를 들어 부모 메소드가 100줄의 코드를 가지고 있을 경우, 자식 메소드에서 1줄만 추가하고 싶더라도 100줄의 코드를 자식 메소드에서 다시 작성해야 한다. 이 문제는 자식 메소드와 부모 메소드의 공동 작업 처리 기법을 이용하면 매우 쉽게 해결이 된다. 자식 메소드 내에서 부모 메소드를 호출하는 것인데, super 키워드와 도트(.) 연산자를 사용하면 숨겨진 부모 메소드를 호출할 수 있다.

 


[ final 클래스와 final 메소드 ]

필드 선언 시에 final을 붙이면 초기값 설정 후 값을 변경할 수 없다. 그렇다면 클래스와 메소드에 final을 붙이면 어떤 효과가 일어날까? final 클래스와 final 메소드는 상속과 관련이 있다.

 

※ final 클래스 : 클래스를 선언할 때 final 키워드를 class 앞에 붙이면 최종적인 클래스이므로 더 이상 상속할 수 없는 클래스가 된다. 즉 final 클래스는 부모 클래스가 될 수 없어 자식 클래스를 만들 수 없다.

 

※ final 메소드 : 메소드를 선언할 때 final 키워드를 붙이면 이 메소드는 최종적인 메소드이므로 오버라이딩할 수 없는 메소드가 된다. 즉 부모 클래스를 상속해서 자식 클래스를 선언할 때, 부모 클래스에 선언된 final 메소드는 자식 클래스에 재정의할 수 없다.

 

[ protected 접근 제한자 ]

public, private 접근 제한자를 사용해서 객체 외부에서 필드, 생성자, 메소드의 접근 여부를 결정했다. 이번에는 또 하나의 접근 제한자인 protected에 대해 알아본다. protected는 상속과 관련이 있고, public과 default의 중간쯤에 해당하는 접근 제한을 한다. default는 접근 제한자가 아니라 접근 제한자가 붙지 않은 상태를 말한다. protected는 같은 패키지에서는 default처럼 접근이 가능하다, 다른 패키지에서는 자식 클래스만 접근을 허용한다. protected는 필드와 생성자 그리고 메소드 선언에 사용될 수 있다. ( 실무에선 잘 쓰이지 않음 )

접근 제한자 제한 대상 제한 범위
protected 필드, 생성자, 메소드 같은패키지이거나, 자식객체만 사용가능

private로 인해 호출 받지 못하는 r
get() 함수를 통해 private r을 return r로 간접적으로 호출 받음


[ 타입 변환 ]

타입변환이란 타입을 다른 타입으로 변환하는 것을 말한다. 기본 타입의 변환에 대해서는 이미 학습했다. 클래스도 마차가지로 타입 변환이 있는데, 클래스의 타입 변환은 상속 관계에 있는 클래스 사이에서 발생한다.

 

※ 자동 타입 변환 : 자동 타입 변환 ( Promotion )은 의미 그대로 자동적으로 타입 변환이 일어나는 것을 말한다. 자동 타입 변환은 다음과 같은 조건에서 일어난다. ( p.309 )

부모 타입 변수 = 자식 타입 객체 ;   => 자식이 부모로 자동 타입 변환

 

자식은 부모의 특징과 기능을 상속 받기 때문에 부모와 동일하게 취급될 수 있다. 예를들어 고양이가 동물의 특징과 기능을 상속받았다면 '고양이는 동물이다'가 성립한다. 그래서 Cat 객체를 생성하고 이것을 Animal 변수에 대입하면 자동 타입 변환이 일어난다.  cat과 animal 변수는 타입만 다를 뿐, 동일한 Cat 객체를 참조한다. 따라서 두 참조 변수의 == 연산 결과는 true가 나온다.   ( class Animal { ... }  <- 상속 UP casting class Cat extends Animal { .. } ) . 

Cat cat = new Cat();   => Animal animal = new Cat() ;도 가능
Animal animal = cat;

cat == animal   => true

 

바로 위의 부모가 아니더라도 상속 계층에서 상위 타입이라면 자동타입변환이 일어날 수 있다. 밑에 표를 보고 이해해보자.

B b = new B();                    A <- B <- D
C c = new C();                       <- C <- E  
D d = new D();
E e = new E();
       =>
A a1 = b;   ( 가능 )           B b1 = d;   ( 가능)           B b3 = e;   ( 불가능 )
A a2 = c ;  ( 가능 )           C c1 = e;   ( 가능 )          C c2 = d;   ( 불가능 )
A a3 = d;   ( 가능 )
A a4 = e;   ( 가능 )

 

부모 타입으로 자동 타입 변환된 이후에는 부모 클래스에 선언된 필드과 메소드만이 접근이 가능하다. 비록 변수는 자식 객체를 참조하지만 변수로 접근 가능한 멤버는 부모 클래스 멤버로 한정된다. 그러나 자식 클래스에서 오버라이딩된 메소드가 있다면 부모 메소드 대신 오버라이딩 된 메소드가 호출된다. 이것은 다형성 ( Polymorphism )과 관련이 있기 떄문에 잘 알아두어야 한다.

 

※ 강제 타입 변환 : 자식 타입은 부모 타입으로 자동 변환 되지만, 반대로 부모 타입은 자식 타입으로 자동 변환 되지 않는다. 대신 다음과 같이 캐스팅 연산자로 강제 타입 변환 ( Casting )을 할 수 있다. 

자식 타입 변수 = ( 자식타입 ) 부모 타입 객체 ;     => 부모가 자식으로 강제 타입 변환 
                          캐스팅 연산자 

 

그렇다고 해서 부모 타입 객체를 자식 타입으로 무조건 강제 변환할 수 있는 것은 아니다. 자식 객체가 부모 타입으로 자동 변환 된 후 다시 자식 타입으로 변환할 때 강제 타입 변환을 사용할 수 있다.

Parent parent = new Child () ;     // 자동 타입 변환
Child child = ( Child ) parent ;     // 강제 타입 변환

 

자식 객체가 부모 타입으로 자동 변환하면 부모 타입에 선언된 필드와 메소드만 사용 가능하다는 제약 사항이 따른다. 만약 자식 타입에 선언된 필드와 메소드를 꼭 사용해야 한다면 강제 타입 변환을 해서 다시 자식 타입으로 변환해야 한다.

 

자동형변환과 강제형변환&nbsp; ( 1 )
자동형변환과 강제형변환&nbsp; ( 2 ) / super(name,a)로 부모호출 Fruit(String name,int a) this.name=name; this.a=a;


[ 다형성 ]

다형성이란 사용 방법은 동일하지만 실행 결과가 다양하게 나오는 성질을 말한다. 자동차의 부품을 교환하면 성능이 다르기 나오듯이 객체는 부품과 같아서, 프로그램을 구성하는 객체를 바꾸면 프로그램의 실행 성능이 다르게 나올 수 있다. 객체 사용 방법이 동일하다는 것은 동일한 메소드를 가지고 있다는 뜻이다. 예를 들어 한국타이어와 금호 타이어는 모두 타이어를 상속하고 있다. 그렇다면 한국 타이어와 금호 타이어는 타이어 (부모) 의 메소드를 동일하게 가지고 있다고 말할 수 있다. 만약 한국 타이어와 금호 타이어가 타이어 (부모)의 메소드를 오버라이딩하고 있다면. 타이어 메소드 호출 시 오버라이딩 된 메소드가 호출된다. 오버라이딩 된 내용은 두 타이어가 다르기 떄문에 실행 결과가 다르게 나온다. 이것이 바로 다형성이다. 다형성을 구현하기 위해서는 자동 타입 변환과 메소드 재정의가 필요하다. 한국 타이어와 금호 타이어는 타이어 타입 (부모)으로 자동 타입 변환이 될 수 있고, 타이어의 메소드를 재정의 하고 있다. ( 자동차는 동일한 타이어 타입으로 한국 타이어와 금호 타이어를 사용하지만 각 타이어의 성능은 다르게 나온다 = 다형성 )  ( 즉, 함수명은 똑같지만 실행 결과는 다르다 )

자동 타입 변환 + 메소드 오버라이딩 => 다형성

 

※ 필드 다형성 : 필드 다형성은 필드 타입은 동일하지만 ( 사용 방법은 동일하지만 ), 대입 되는 객체가 달라져서 실행결과가 다양하게 나올 수 있는 것을 말한다. 다음 Car 클래를 보면서 이해해보자.

public class Car {
  public Tire tire;   // 필드 선언

   public void run() {  // 메소드 선언
       tire.roll();   //  => tire 필드에 대입된 roll() 메소드 호출
    }
}

 

Car 클래스에는 Tire 필드가 선언되어 있다. 먼저 Car 객체를 생성한 후 타이어를 장착하기 위해 다음과 같이 HankookTire 또는 KumhoTire 객체를 Tire 필드에 대입할 수 있다. 왜냐하면 자동 타입 변환이 되기 떄문이다.

Car myCar = new Car();    //  => Car 객체 생성

myCar.tire = new HankpookTire();   //  => HankookTire 장착

myCar.tire = ne KumhoTire();   //  => KumhoTire 장착

Car 클래스의 run() 메소드는 tire 필드에 대입된 객체의 roll() 메소드를 호출한다. 만약 HankookTire와 KumhoTire가 roll() 메소드를 재엉의하고 있다면, 재정의된 roll() 메소드가 호출된다. 따라서 어떤 타이어를 장착했는지에 따라 roll() 메소드의 실행 결과는 달라지게 된다 이것이 바로 필드의 다형성이다. 

myCar.run();   => 대입된(장착된) 타이어의 roll() 메소드 호출

상속의 다형성과 @Override / 위에 설명 참고

 

※ 매개변수 다형성 : 다형성은 필드보다는 메소드를 호출할 때 많이 발생한다. 메소드가 클래스 타입의 매개변수를 가지고 있을 경우, 호출할 때 동일한 타입의 객체를 제공하는 것이 정석이지만 자식 객체를 제공할 수도 있다. 여기서 다형성이 발생한다. 다음과 같이 Driver라는 클랫가 있고, Vehicle 매개벼수를 갖는 drive() 메소드가 정의되어 있다고 가정해보자. drive() 메소드는 매개밧으로 전달 받은 vehicle의 run() 메소드를 호출한다.

public class Driver {
   public void drive(Vehicle vehicle) {
      vehicle.run() ;
   }
}

일반적으로 drive() 메소드를 호출한다면 다음과 같이 Vehicle 객체를 제공할 것이다.

Driver driver = new Driver();
Vehicle vehicle = new Vehicle();
driver.drive(vehicle);

그러나 매개값으로 Vehicle 객체만 제공할 수 있는 것은 아니다. 자동 타입 변환으로 인해 Vehicle의 자식 객체도 제공할 수 있다.

Briver driver new Driver();
Bus bus = new Bus();
driver.drive( bus );  //  => Bus 객체의 run() 호출. 자동 타입 변환 발생 Vehicle vehicle = bus;

drive() 메소드는 매개변수 vehicle 이 참조하는 객체의 run() 메소드를 호출하는데, 자식 객체가 run() 메소드를 제정의 하고 있다면 재정의 된 run() 메소드가 호출된다. 그러므로 어떤 자식 객체가 제공되느냐에 따라서 drive()의 실행 결과가 달라진다. 이것이 매개변수의 다형성이다.

void drive( Vehicle vehicle ) {   //   =>  여기서 Vehicle은 자식객체
    vehicle.run();    //  => 자식 객체가 재정의한 run() 메소드 호출
}

[ 객체 타입 확인 ]

매개변수의 다형성에서 실제로 어떤 객체가 매개값으로 제공되었는지 확인하는 방법이 있다. 꼭 매개변수가 아니더라도 변수가 참조하는 객체의 타입을 확인하고자 할 때, instanceof 연산자를 사용할 수 있다. instanceof 연산자의 좌황에는 객체가 오고 우항에는 타입이 오는데, 좌항의 객체가 우항의 타입이면 true 산출하고 그렇지 않으면 false를 산출한다.

boolean result = 객체 instanceof 타입;

instanceof 연산자

 

[ 추상 클래스 ]  ( 실무에서 잘 쓰이지 않음 )

사전적 의미로 추상 ( abstract ) 은 실체 간에 공통되는 특성을 추출한 것을 말한다. 예를 들어 새, 곤충, 물고기 등의 공통점은 동물이다. 여기서 동물은 실체들의 공통되는 특성을 가지고 있는 추상적인 것이라고 볼 수 있다. 객체를 생성할 수 있는 클래스를 실체 클래스라고 한다면, 이 클래스의 공통적인 필드나 메소드를 추출해서 선언한 클래스를 추상 클래스라고 한다. 추상 클래스는 실체 클래스의 부모 역할을 한다. ( 빈 껍데기 같은 느낌 추상클래스는 부모클래스임 ) 따라서 실체 클래스는 추상 클래스를 상속해서 공통적인 필드나 메소드를 물려받을 수 있다. 예를 들어 Bird, Insect, Fish와 같은 실체 클래스에서 공통되는 필드와 메소드를 따로 선언한 Animal 클래스를 만들 수 있고, 이것을 상속해서 실체 클래스를 만들 수 있다. 추상 클래스는 실체 클래스의 공통되는 필드와 메소드를 추출해서 만들었기 때문에 new 연산자를 사용해서 객체를 직접 생성할 수 없다. ( 직접 객체를 생성할 수 없고, 상속만 할 수 있다. 자식 클래스에서 재정의 (오버라이딩) 할 수 있다. 재정의하지 않으면서 자식 클래스도 추상 클래스가 되어야 한다. )

      ※ 추상클래스 안에는 일반적인 메소드, 추상 메소드 둘 다 가능 하지만,

      ※ 추상 메소드에는 반드시 추상 클래스 안에 있어야 한다 !!! 

Animal animal = new Animal ();   // x

추상 클래스는 새로운 실체 클래스를 만들기 위한 부모 클래스로만 사용된다. 즉, 추상 클래스는 extends 뒤에만 올 수 있다.

class Fish extends Animal {
   ...
}

 

※ 추상 클래스 선언 : 클래스 선언에 abstract 키워드를 붙이면 추상 클래스 선언이 된다. ( abstract 가 보이면 추상클래스다 라고 기억하기 ) 추상 클래스는 new 연산자를 이용해서 객체를 직접 만들지 못하고 상속을 통해 자식 클래스만 만들 수 있다. 추상 클래스도 필드, 메소드를 선언할 수 있다. 그리고 자식 객체가 생성될 때 super()로 추상 클래스의 생성자가 호출되기 때문에 생성자도 반드시 있어야 한다.

public abstract class 클래스명 {
     // 필드 // 생성자 // 메소드
}

※ 추상 메소드와 재정의 : 자식 클래스들이 가지고 있는 공통 메소드를 뽑아내어 추상 클래스로 작성할 때, 메소드 선언부 (리턴타입, 메소드명, 매개변수)만 동일하고 실행 내용은 자식 클래스마다 달라야 하는 경우가 많다. 일반 메소드 선언과의 차이점은 abstract 키워드가 붙고, 메소드 실행 내용인 중괄호 { } 가 없다. 추상 메소드는 자식 클래스의 공통 메소드라는 것만 정의할 뿐, 실행 내용을 가지지 않는다.

abstract 리턴타입 메소드명 ( 매개변수, ... ) ;

추상 메소드는 자식 클래스에서 반드시 재정의 ( 오버라이딩 ) 해서 실행 내용을 채워야 한다.

public abstract class Animal {
   abstract void sound() ;
}

추상 메소드

abstract class Ca{
	abstract int add(int a, int b);
	abstract double avg(int a[]);  //선언만 하고 
}
class Cal extends Ca{  //구현은 추상클래스 상속받아서 해야한다
	@Override
	int add(int a, int b) {
		return a+b;
	}
	@Override
	double avg(int a[]) {  //배열 평균
		//for-each문으로  //int a[]=new int[] {1,2,3};
		int sum=0;
		for(int k:a) {  // for-each 문
			sum+=k;
		}
		return ((double)sum/a.length);
	}
}
public class Test {
	public static void main(String[] args)  {
		
		Cal c=new Cal();
		System.out.println(c.add(3,7));
		System.out.println(c.avg(new int[] {1,2,3}));
		
	}
}

[ 봉인된 클래스 ]

기본적으로 final 클래스를 제외한 모든 클래스는 부모 클래스가 될 수 있다. 그러나 Java 15 부터는 무분별한 자식 클래스 생성을 방지하기 위해 봉인된 ( sealed ) 클래스가 도입되었다.


[ 객체 배열 ]

동일 타입의 여러 객체를 생성하여 사용할 때는 객체 배열을 사용한다. 주의할 점은 객체 배열 안에 객체가 저장되는 것이 아니라, 객체의 주소가 저장된다는 점이다. 즉, 객체 배열은 참조변수들을 하나로 묶은 참조 변수 배열인 것이다.

객체를 생성해서 객체 배열의 각 요소에 저장하는 것을 잊지 말자.

객체 배열 : 객체를 저장할 수 있는 공간 (타입: 클래스)

 

객체 배열 ( 2 )
객체 배열 ( 3 )
객체 배열 ( 4 )
객체 배열 ( 5 )

abstract class Profile{  // 추상클래스
	abstract void add(String name, String id);  // 추상메소드
	abstract String check(String id);
}
class Person {
	String name, id;
	Person(String n, String i) {
		name=n; id=i;
	}
	public String getName() {
		return name;
	}
	public String getId() {
		return id;
	}
}
class Per extends Profile {
	Person[] ary; // 객체 배열 선언
	int n;
	
	Per(int n){ // 생성자
		ary=new Person[n]; // 배열 생성하고 있음
	}
	 void add(String name, String id) {
		 ary[n]=new Person(name,id); // 객체 생성 코드
		 n++;
	 }
	 String check(String id) {
		 for(int i=0;i<n;i++) {
			 if(id.compareTo(ary[i].getId())==0) {
				 return ary[i].getName();
				 }
		 }
		 return null;
	 }
}
public class Test {
	public static void main(String[] args) {

		Profile p = new Per(5);
		p.add("현욱","123"); // 현욱 ary[0].name에 위치 / 123 ary[0].id에 위치
		p.add("예준","456"); // ary[1].name  ary[1].id
		p.add("태경","344"); // ary[2].name  ary[2].id
		
		System.out.println(p.check("123"));
		System.out.println(p.check("456"));
		System.out.println(p.check("457"));

	}
}

[ 복습 정리 ]

Q. 복권의 번호와 추첨한 복권의 번호를 확인하여 일치하는 번호의 개수를 출력하는 프로그 램. 두 배열은 main함수에 선언하고 두 배열에서 일치하는 번호를 찾아 그 개수를 반환 해라.

 

자동형변환 강제형변환 ( 1 )
자동형변환 강제형변환 ( 2 )
클래스 복습 ( 1 )

 

클래스 복습 ( 2 )
상속 복습 ( 1 )
상속 복습 ( 2 ) // size는 private라서 바로 호출 불가 getSize() 함수로 간접 호
상속 복습 ( 3 )
상속 복습 ( 4 )
상속 복습 ( 5 )
상속 복습 ( 6 )

 

Q. 두 사람이 가위바위보를 한다. 가위,바위,보 중 하나를 문자열로 입력받아 누가 이겼는지 판단하는 프로그램을작성해라.(중첩 if문 사용해야함, 문자열 비교)

실행결과) 영수 : 가위  철수 : 보  철수가 이겼다.

import java.util.Scanner;

public class Test {
	public static void main(String[] args) {
		
		Scanner sc = new Scanner(System.in);
		
		System.out.println("영수: ");
		String input  = sc.nextLine();
		System.out.println("철수: ");
		String input2  = sc.nextLine();
		
		String stone = "바위";
		String sissor = "가위";
		String paper = "보";
		
		if(input.equals(stone)) {
			if(input2.equals(sissor)) {
			System.out.println("영수가 이겼다");
			}
			else if (input2.equals(paper)) {
				System.out.println("철수가 이겼다");
			}
			else if (input2.equals(input)) {
				System.out.println("비겼다 !!!");
			}
		}
		if(input.equals(sissor)) {
			if(input2.equals(paper)) {
			System.out.println("영수가 이겼다");
			}
			else if (input2.equals(stone)) {
				System.out.println("철수가 이겼다");
			}
			else if (input2.equals(input)) {
				System.out.println("비겼다 !!!");
		}
		if(input.equals(paper)) {
			if(input2.equals(stone)) {
			System.out.println("영수가 이겼다");
			}
			else if (input2.equals(sissor)) {
				System.out.println("철수가 이겼다");
			}
			else if (input2.equals(input)) {
				System.out.println("비겼다 !!!");
		}
	}
}
	}
}

상속 extends super() 

class Person{
	private String name;
	
	Person(String name) {
		this.name=name;
	}
	public void name() {
		System.out.println(name);
	}
}  // 부모 클래스의 생성자 = 슈퍼 클래스 = 상위 클래스
class Student extends Person {  // Person이 부모 Student가 자식
	private String major; 
	private String school; //major와 school은 부모에 없는 자식에 추가한 것 
	
	// 자식 클래스의 생성자 = 서브 클래스 = 하위 클래스
	Student(String name, String major, String school) { 
		super(name);  // super() 부모 생성자 호출 // 부모의 this.name=name; 실행됨
		this.major=major;
		this.school=school;  // 부모에 없는 자식에 추가한 것 그래서 따로 초기화 해줌
	}
	void show() {
		name();
		System.out.println(major);
		System.out.println(school);
	}
}
public class Test {

	public static void main(String[] args) {

		Person p = new Person("길동");  // 부모 클래스의 객체 생성 코드
		p.name();  // 길동 출력
		
		Student s = new Student("동글","컴퓨터","컴공");  // 자식 클래스의 객체 생성 코드
		s.show();  // 동글,컴퓨터,컴공 출력
        
        p.show();  // 에러
        s.name="lala";  // 에러
		
	}
}

 => p.show(); 는 에러 왜냐햐면 show는 자식에만 있어서 부모로는 불러올 수 없음. s.show()만 가능                                     => s.name="lala"; 는 에러 왜냐하면 생성자 안에 들어간 name은 사용 가능 하나 직접적인 필드에 있는 name은 private이기 때문에 외부에서 접근 불가

 

 

 

728x90