객체구성문법(한 개 클래스 간 문법)
접근제어자 class 클래스명 {
멤버 필드 변수 (접근 제어자, 자료형, 변수명)
메서드 (접근 제어자 리턴형(없으면 void 형) 메서드 명 () {} )
}
*인스턴스 / 클래스(static)
*특별 메서드 (main, 생성자)
*오버로딩
*가변인자 등등
객체지향프로그램 기법(여러개의 클래스간 문법화)
캡슐화(은닉화) - 접근제어자, setter/getter
상속(extends)
추상
다형
= 공통 내용의 모듈화
단일 상속이 기본(다중 상속을 편법으로 만들어야 하는 경우 있다)
조상(Object) - extends 라는 상속 구문이 없으면 컴파일러가 무조건 Object 상속 받는다.
class Parent { //extends Object 가 생략된 것
void viewParent() {
System.out.println("viewParent 호출");
}
}
class Child extends Parent { //상속
void viewChild() {
System.out.println("viewChild 호출");
}
}
public class Extend1 {
public static void main(String[] args) {
Child c = new Child();
c.viewChild();
c.viewParent();
System.out.println(c.toString());
Parent p = new Parent();
p.viewParent();
//Object에서 가져온 것
System.out.println(p.toString());
}
}
class Parent { //extends Object 가 생략된 것
void viewParent() {
System.out.println("viewParent 호출 : " + this);
}
}
class Child extends Parent {
void viewChild() {
System.out.println("viewChild 호출 : " + this);
}
}
public class Extend2 {
public static void main(String[] args) {
Child c = new Child();
System.out.println(c);
c.viewChild();
c.viewParent();
Parent p = new Parent();
}
}
상속 관계에 있더라도 private 선언한 변수나 메서드는 실행되지 않는다.
class Parent { //extends Object 가 생략된 것
private String p1 = "홍길동";
public String p2 = "박문수";
String p3 = "이몽룡";
void viewParent() {
System.out.println("viewParent 호출 : " + this);
}
}
class Child extends Parent {
void viewChild() {
System.out.println("viewChild 호출 : " + this);
//System.out.println(p1); --> 에러
System.out.println(p2);
System.out.println(p3);
}
}
class GrandChild extends Child {
void viewGrandChild() {
System.out.println("viewGrandChild() 호출 : " + this);
}
}
public class Extend3 {
public static void main(String[] args) {
GrandChild g = new GrandChild();
g.viewParent();
Child c = new Child();
//System.out.println(c.p1); --> 에러
System.out.println(c.p2);
System.out.println(c.p3);
}
}
부모(조상) 클래스에 정의된 기능을 자식 클래스에서 적합하게 수정해서 재정의하는 것
오버라이딩 조건 (상속 관계가 전제)
1. 메서드 이름, 매개변수(개수, 순서, 타입), 리턴 타입은 부모 클래스와 같아야 한다.
2. 접근 제한자는 부모 메서드보다 같거나 넓어야 한다.
3. 부모 클래스 메서드보다 더 상위의 예외를 던질 수 없다.
오버라이딩
class Parent {
void viewParent() {
System.out.println("viewParent 호출 : " + this);
}
}
class Child extends Parent {
void viewParent() {
System.out.println("child viewParent 호출 : " + this);
}
}
public class Overriding1 {
public static void main(String[] args) {
Child c = new Child();
c.viewParent();
}
}
오버로딩
class Parent {
void viewParent() {
System.out.println("viewParent 호출 : " + this);
}
}
class Child extends Parent {
void viewParent(int a) { --> 이 경우는 오버로딩이다.
System.out.println("child viewParent 호출 : " + this);
}
}
public class Overriding1 {
public static void main(String[] args) {
Child c = new Child();
c.viewParent();
c.viewParent(10); --> 따라서 이 두개는 오버로딩(오버라이딩 아님)
}
}
여기서 리턴문 형식으로 써준다면 에러가 뜬다
class Parent {
void viewParent() {
System.out.println("viewParent 호출 : " + this);
}
}
class Child extends Parent {
int viewParent() { --> 에러! 자료형식과 리턴문이 있어 오버라이딩 할 수 없음
System.out.println("child viewParent 호출 : " + this);
return 10;
}
}
public class Overriding1 {
public static void main(String[] args) {
Child c = new Child();
c.viewParent();
}
}
오버라이딩 할 수 없다는 에러문구
부모에 접근 (부모 객체 참조)
(this : 자식 / super : 부모 라고 생각)
class Parent {
String p = "홍길동";
void viewParent() {
System.out.println("viewParent 호출 : " + this);
}
}
class Child extends Parent {
String p = "박문수";
void viewParent() {
System.out.println("child viewParent 호출 : " + this);
//super 키워드 (this:나 super:부모)
super.viewParent(); --> 부모의 viewParent 메서드 호출
System.out.println(p);
System.out.println(this.p); --> 자식 p 호출 (박문수)
System.out.println(super.p); --> 부모 p 호출 (홍길동)
}
}
public class Overriding2 {
public static void main(String[] args) {
Child c = new Child();
c.viewParent();
}
}
class Parent {
Parent() {
System.out.println("Parent 생성자 호출");
}
}
class Child extends Parent {
Child() {
System.out.println("Child 생성자 호출");
}
}
public class Constructor4 {
public static void main(String[] args) {
Child c = new Child();
}
}
부모가 기본 생성자가 아닌 다른생성자일 경우 super()를 사용하여 호출한다.
super도 this처럼 문장 맨 첫 줄에 있어야 한다 (주석 이외)
class Parent {
// Parent() {
// System.out.println("Parent 생성자 호출");
// }
Parent(String data) {
System.out.println("Parent(String data)생성자 호출");
}
}
class Child extends Parent {
Child() {
//super : 멤버 / super() : 메서드 / this/this() 구조와 같다.
//this 처럼 문장의 첫 줄에 있어야한다(주석 이외)
super("10");
System.out.println("Child 생성자 호출");
}
}
public class Constructor4 {
public static void main(String[] args) {
Child c = new Child();
}
}
final이 붙어진 클래스는 상속할 수 없다.
final 종류
final 클래스 --> 상속 불가
final 메서드 --> 재정의(오버라이딩) 불가
final 변수 --> 값 변경 불가
상수는 final static 형식으로 많이 쓴다.
final class Parent { // 상속 불가
Parent() {
System.out.println("Parent 생성자 호출");
}
}
class Child extends Parent {
Child() {
System.out.println("Child 생성자 호출");
}
}
public class Final1 {
public static void main(String[] args) {
Child c = new Child();
}
}
class에 final로 인하여 뜨는 에러
class Parent {
Parent() {
System.out.println("Parent 생성자 호출");
}
final void viewParent() { // --> final로 인하여 오버라이딩 할 수 없다.
System.out.println("Parent viewParent 호출");
}
}
class Child extends Parent {
Child() {
System.out.println("Child 생성자 호출");
}
void viewParent() {
System.out.println("Child viewParent 호출");
}
}
public class Final1 {
public static void main(String[] args) {
Child c = new Child();
c.viewParent();
}
}
메서드에 final을 붙일 경우 오버라이딩 할 수 없다고 뜨는 에러
다형성(Polymorphism)
부모 타입 변수로 여러 자식 객체들을 호출하고 싶을 때 사용(다형성)
부모는 변하지 않지만, 부모 하나로 여러 자식들의 특성들을 사용하는 것
다형성의 예
class Parent {
void viewParent() {
System.out.println("Parent 호출");
}
}
class Child1 extends Parent {
void viewParent() {
System.out.println("Child1 호출");
}
}
class Child2 extends Parent {
void viewParent() {
System.out.println("Child2 호출");
}
}
public class Casting3 {
public static void main(String[] args) {
// Child1 c1 = new Child1();
// c1.viewParent();
// Child2 c2 = new Child2();
// c2.viewParent();
Parent p = new Child1(); --> child1 참조 가능
p.viewParent();
p = new Child2(); --> child2 참조 가능
p.viewParent();
}
}
class를 보관하기 위한 폴더
package이름 - 도메인 형식(회사 도메인)으로 작성
ex > package com.naver.www << 반대로 작성
같은 클래스 이름이라도 패키지가 다르다면 사용 가능하다.
패키지는 기존의 컴파일 방식과는 다른 방법으로 시켜주어야 한다.
컴파일 - javac -d . -encoding utf-8 packB.java(기존 것에서 -d . 추가,
폴더 만들어지고 안에 packB.class가 들어가짐)
jdk 10 버전 이하
{
패키지
클래스
...
}
jdk 10 이상
{
모듈 (현업에서는 아직까진 잘 사용하지 않음)
패키지
클래스
...
}
package 패키지명 --> class를 이 패키지명을 통해서 안에 넣는다는 뜻
class 클래스명 {
}
import 패키지명.클래스명 --> 패키지 안의 클래스를 가져오는 기능
1.packC.java 생성(위에 package pack2 라고 쓰기)
다른 패키지에 선언된 클래스를 사용하기 위해 필요한 키워드
package에 모든 클래스를 포함할 때는 *를 사용한다.