열심히 끝까지
디바이스 융합 자바(Java) day10 - 학생부(삭제),접근제어자,상속,super(부모의 생성자 호출),상수,오버라이딩 본문
디바이스 융합 자바(Java) day10 - 학생부(삭제),접근제어자,상속,super(부모의 생성자 호출),상수,오버라이딩
노유림 2022. 6. 20. 17:54[지난주]
- OOP(객체지향언어) // 삭제는 6/20에 나감
: 객체지향의 가장 기본적인 단위 = class
: 생성자를 main()에 생성
: 기본생성자 외에 답을 미리 넣어놓어 초기화 시켜놓고 싶으면
클래스에서 오버로딩하여 작성
: 객체배열은 클래스의 객체로 배열을 만드는 작업
방법
Point[] data = new Point[3];
: index = 2
[ A A a ] <- 대문자 데이터 저장 o , 소문자 데이터 저장 x
==> 1, 2 -> 0, 1인덱스의 데이터 변경
------저번 주 한 것
package class01;
// OOP(객체지향언어)
class Point{
// 객체지향의 가장 기본적인 단위 = class
int x;
int y;
static int z; // 클래스 변수 == 공유자원
void showInfo() {
System.out.println(this.x + ", " + this.y);
}
Point(){
this(0,0);
}
Point(int x, int y){ // 오버로딩
this.x = x;
this.y = y;
}
}
public class Test01 {
public static void main(String[] args) {
Point p1 = new Point(); // 기본생성자
Point p2 = new Point(10, 20);
Point[] data = new Point[3]; // 객체배열
data[0] = new Point(1,2);
data[1] = p2;
data[2] = p1;
for(int i = 0; i < data.length; i++) {
data[i].showInfo();
}
}
}
[오늘]
- 삭제 방법
[ 1 | 3 | 4 | | ]
: 5개짜리 배열을 만들어 놓고
: 2라는 애를 넣을 적에 정렬된 상태로 넣고 싶어서..
구조가 정해져있기 때문에 제거가 불가능
=> 초기값을 0으로 바꾸는 것밖에 못함
: 값이 0이면 새로운 값을 넣을게? => 로직 짤 수 있음
: 하지만 100만 개 값에서 찾기 힘들 뿐더러
만약 레알 값이 0이면 값이 사라져버리기 때문에.. 위 로직 무리..
: 배열의 삭제가 존재하는 이유?
최근에 넣은 데이터를 삭제
=> stack 개념이랑 이어짐
데이터 존재 없으면 0 -> ++되면 1 -> ++되면 2 -> ...
3명 넣으면 index는 3이 되고 최근에 입력한 2의 값을 지우도록 할 것
새로운 것을 넣으면 덮어쓰기가 가능하기 때문에 지운 것이 맞게 된다.
=> 가비지컬렉터가 나중에 제거해 줄 예정
--------------목요일에 한 학생부에 삭제 추가한 로직
package class04;
import java.util.Scanner;
class Student{
String name;
int score;
void showInfo() {
System.out.println(this.name + "학생은 " + this.score + "점입니다.");
System.out.println();
}
Student(String name, int score){
this.name = name;
this.score = score;
System.out.println(this.name + "학생 입력완료!");
System.out.println();
}
}
public class Test09 {
public static void main(String[] args) {
// 학생부 프로그램
// 학생 정보를 배열에 저장해서 관리하는 프로그램
// 학생정보를 가리키는 형은 없기 때문에 class 생성
// 핵심 로직
// 비즈니스 메서드
// CRUD(생성, 출력, 변경, 삭제)
Student[] data = new Student[3]; // 데이터는 3칸 저장 가능
// data.length -> 최대크기
int index = 0; // 저장, index : 현재 저장된 학생수
Scanner sc = new Scanner(System.in) ;
while(true) {
System.out.println("1. 추가");
System.out.println("2. 출력");
System.out.println("3. 변경");
System.out.println("4. 삭제");
System.out.println("5. 종료");
System.out.print("입력 > ");
int act = sc.nextInt();
// 사용자가 입력하면 -> 유효성 검사!
if(act == 1) { // 추가 => 유효성 검사 + 인덱스 체크
if(index == data.length) {
System.out.println("데이터공간이 부족합니다.");
continue;
}
System.out.print("학생 이름 입력 : ");
String name = sc.next();
System.out.print("학생 성적 입력 : "); // 0부터 100까지
int score = sc.nextInt();
data[index] = new Student(name, score); // 객체를 만들기만 하고 초기화는 안했다.
index++; // 후위 증감 연산자, data[index++]라고 해도 되나 보기 불편함으로..
}
else if(act == 2) { // 출력
if(index == 0) { // 인덱스가 0 하나도 안 차 있으면
System.out.println("저장한 정보가 없습니다");
// 사용자의 편의성 고려(인원이 없는 것을 출력을 원하는 즉시 알게 됨
continue;
}
System.out.println("===학생 목록===");
for(int i = 0; i < index; i++) {
data[i].showInfo();
}
}
else if(act == 3) { // 변경
if(index == 0) { // 인덱스가 0 하나도 안 차 있으면
System.out.println("저장한 정보가 없습니다");
// 사용자의 편의성 고려(인원이 없는 것을 출력을 원하는 즉시 알게 됨
continue;
}
System.out.print("정보를 변경할 학생의 번호 입력 : ");
int num = sc.nextInt();
num--; // 번호와 인덱스 넘버의 차이
if(num < 0 || index <= num) { // 올바르지 않은 입력 시
System.out.println("없는 번호입니다! 확인 후 다시 이용해주세요~~");
System.out.println();
continue;
}
System.out.print("변경할 점수 입력 : ");
data[num].score=sc.nextInt();
System.out.println(data[num].name + "학생 변경완료");
System.out.println();
}
else if(act == 4) { // 최근 데이터 삭제
if(index == 0) {
System.out.println("삭제할 데이터가 없습니다!");
continue;
}
System.out.println("최근 데이터 삭제중...");
index--;
System.out.println("삭제 완료!");
}
else if(act == 5) { // 종료
System.out.println("종료됩니다...");
break;
}
else { // 이외의 숫자를 입력 시
System.out.println("잘못된 입력입니다.");
// 필요없는 제어문을 쓰지 않아도 되기 때문에
// continue
}
}
}
}
-----------------------오늘 자 새로운 진도
- 접근제어자, 접근자(캡슐화와 관련)
: 개발자의 악의적인 접근, 혹은 실수로 접근하여 잘못 출력되는 것을 방지하기 위해..!
- 직접적인 접근도 막기 위해서
=> 정보 은닉 ( 캡슐화 )
: 멤버변수의 값을 나를 통해서만 진행(접근)할 수 있게 하는 것
: private(<=>public(공개, 오픈)과 반대되는 것)
: private를 건 클래스 내부에서는 변경 가능하나, main문에서는 변경 불가능
: ex ) 이름과 시험을 바꿀 수 밖에 없는 상황이 생기게 되면(변경하거나 출력하기 위해서)
: 이때 사용하는 것이 getter, setter
- getter, setter
: private으로 직접 접근할 수 없는 멤버변수의 값을
출력(getter)하거나, 변경(값대입)(setter)하기 위해서 사용
- getter 사용법(값 새로 세팅)
String getName() {
return this.name;
}
int getScore() { // getter는 인자는 없고 outter는 있게 만드는 것
return this.score;
}
- setter 사용법(값 새로 대입)
void setName(String name) {
this.name = name;
}
void setScore(int score) { // 인자는 있는데 outter가 없는 상황
this.score = score;
}
// 동일 패키지에 같은 이름의 class가 존재할 수 없음
// 만약 class02에 Student 클래스가 있었으면 이 클래스에서 생성 불가
// field : 속성, 애트리뷰트(첫 OOP 배울 때)
: 클래스의 필드 속성은 많아질 수 있음
: 일일이 만드는 것은 귀찮...
우클릭 -> Source -> Gererate Getter, Setter
- 실제 멤버변수랑은 다르게 public을 붙여서 출력하거나 값을 변경하거나 할 수 있게 한다
- 값을 변경할거면 그냥 쓰지 왜 getter, setter를 이용하는가?
: 로그를 남기기 위해서! -> 기록을 남기다!
>> 메서드를 호출할 때 로그가 남는다.
>> 함수까지 호출해서 완전 로그를 남기기 위해서!
>> 프레임워크 자동 생성을 활용하여 생성 -> 자바에서도 미리 개발을 할 때 사용해볼 것
>> 멤버변수 직접접근을 방지
>> 대신 메서드를 통해 접근
-> 로그나 각종 프레임 워크에서 자동으로 연동하는 것들을 이용할 예정
>> 이름의 형식이나 스타일 등은 유지가 됨
-> 마음대로 만들 수 없음
-> 정해진 형식대로 만들 것
★ 멤버변수에 직접접근을 하는 것을 막아주는 메서드 : getter, setter
package class02;
// 접근제어나 , 접근자
class Student{ // 동일 패키지에 같은 이름의 class가 존재할 수 없음
// 만약 class02에 Student 클래스가 있었으면 이 클래스에서 생성 불가
private String name;
private int score;
// getter, setter
// : private으로 직접접근할 수 없는 멤버변수의 값을
// 출력하거나(getter), 변경(값대입)하기 위해서(setter) 사용
void setName(String name) {
this.name = name;
}
void setScore(int score) { // 인자는 있는데 outter가 없는 상황
this.score = score;
}
String getName() {
return this.name;
}
int getScore() { // getter는 인자는 없고 outter는 있게 만드는 것
return this.score;
}
void showInfo() {
System.out.println(this.name + " " + this.score);
}
Student(String name, int score){
// 클래스 내부에서는 this.로 대입할 수 있다.
// 하지만 main문에서는 불가능
this.name = name;
this.score = score;
System.out.println(this.name + "학생 입력 완료!");
}
}
// -----------위가 설계 아래가 출력
public class Test03 {
public static void main(String[] args) {
Student[] data = new Student[2];
data[0] = new Student("홍길동", 30);
// data[0].name = ""; // 실수로 접근
data[1] = new Student("아무무", 80);
// data[0].score = 100; // 악의적인 접근(과하게 이야기..하게 되면!), 혹은 아차 실수!!
// private로 지정하면
for(int i = 0; i < data.length; i++) {
data[i].setScore(100); // data[i].score = 100;
System.out.println(data[i]);
data[i].showInfo();
}
}
}
-----강사님 문제
package class02;
class Point{
private int x;
private int y;
// 멤버변수에 직접접근을 하는것을 막아주는 메서드 : getter,setter
Point(int x,int y){
this.x=x;
this.y=y;
}
}
public class Test04 {
public static void main(String[] args) {
Point[] data=new Point[3];
data[0]=new Point(1,2);
data[1]=new Point(10,11);
data[2]=new Point(3,45);
data[0].x=10;
data[0].y=10;
System.out.println("("+data[0].x+","+data[0].y+")");
for(int i=0;i<data.length;i++) {
System.out.println(data[i].x +"|"+data[i].y);
}
}
}
// 멤버변수에 직접접근을 하는 것을 막아주는 메서드 : getter, setter
getter, setter 이용하여 출력 나오게 하는 법
package class02;
class Point{
private int x;
private int y;
public void setX(int x) {
this.x = x;
}
public int getX(){
return x;
}
public void setY(int y) {
this.y = y;
}
public int getY() {
return y;
}
// 멤버변수에 직접접근을 하는것을 막아주는 메서드 : getter,setter
Point(int x,int y){
this.x=x;
this.y=y;
}
}
public class Test04 {
public static void main(String[] args) {
Point[] data=new Point[3];
data[0]=new Point(1,2);
data[1]=new Point(10,11);
data[2]=new Point(3,45);
data[0].setX(10);
data[0].setY(10);
System.out.println("("+data[0].getX()+","+data[0].getY()+")");
for(int i=0;i<data.length;i++) {
System.out.println(data[i].getX() +"|"+data[i].getY());
}
}
}
- 상속
ex )
몬스터 - 상위, 부모 클래스
피카츄, 파이리, 꼬부기, ... - 하위, 자식 클래스
사람
학생, 선생님, ...
점 (상하위)
+ 색깔 => 색깔점 (뭔가를 추가해서 상속)
>> 상속 : 상하관계, 기존에서 추가해서 만들 때, 상속관계 생성
- 상속은 다중상속 불가
- 상속받는 클래스 : 자식, 하위 클래스
- 상속하는 클래스 : 부모, 상위 클래스
- 부모의 멤버변수, 메서드를 자식이 사용 가능
but, 부모는 자식클래스를 참조할 수 없다.(자식클래스의 내부를 볼 수 없다)
- Shape에 모든 코드를 Circle이 가져다 사용할 수 있다.
>> ★★★★★ 모든 자식 생성자에서는 가장 먼저 부모의 기본생성자를 호출한다!!!!
>> 부모의 생성자를 호출하는 생성자가 숨어있다!!!!
------------강사님 문제
package class03;
class A{
int a;
int b;
A(){ // 기본생성자를 호출하거나
System.out.println("A 기본생성자");
}
A(int a,int b){
this.a=a;
this.b=b;
System.out.println("A 생성자");
}
}
class B extends A{
int c;
B(){
// 부모에게 기본생성자가 없다면, 모든 자식생성자에서 문제 발생!!!!★★★★★
// 다른 해결법
super(10, 20)
this.c=0;
System.out.println("B 생성자");
}
}
public class Test06 {
public static void main(String[] args) {
A aaa=new A(123,123);
B bbb=new B();
}
}
>> 부모의 기본생성자가 없으면 모든 자식생성자에서 문제가 발생한다
그러니 부모는 생성자를 만들고 기본 생성자도 꼭 만들어주어야 한다!!!
if, 위의 문제에서 A(){ }가 존재하지 않는다면
B 클래스에서는 어떤 생성자를 만들더라도 문제가 발생한다!
-----------
앞으로 우리는..
설계를 하고 나서...
개발 -> 중간 피드백 -> 오류 점검 -> 테스트 -> 출시
>> 전체 프로세스 대충 설명 시....
>> 제일 오래 걸리는 것이 설계
설계가 탄탄히 잘 될 수록 오래 걸리고,
설계를 만들게 되면 설계를 건들이지 않는다.
설계를 하고 과정을 진행하다가 무언가를 빼먹었다고 한다면
그것은 설계를 잘못한 것이다(시간을 짧게 잡은 것이다).
실무에서 하위 클래스인 B를 코딩하고 있는 상황은
A의 설계가 완료되었음을 의미한다.(나머지 개발자도 A의 클래스 사용 중)
>> A는 픽스다!!
그런데 만약에 A에 문제가 발생하다면...(A의 기본생성자를 사용하지 않는 상황은)?
=> A에게 존재하는 다른 생성자를 사용해서, 나의 A부분을 완성!
전체 정리
class A, B
>> A에게 기본생성자가 없어서 생긴 문제에요~
>> 생성해줘서 해결!
>> 그런데 A에게 기본생성자가 없다는 소리는?
: 없이 쓰려고 만든 것!!!
=> 설계를 고치면 안된다!(부모를 고치면 안된다)
>> 다른 생성자를 사용하여 설계
기본생성자인 super();가 원래 생성되어 있기 때문에
안써도 괜찮았지만 기본생성자가 아닌 생성자일 경우, super()에 값을 넣어서
자식클래스에 만들어 주어야 함
A(int a, int b)를 가져오기 위해서
super(int a, int b);로 작성하기
Circle(String name) { // 및줄 그어진 Circle을 이용해 생성하게 되면?
// 부모에게 기본생성자가 없는 상황에서는 추천 해결방법 알려주기
// 부모에게 기본생성자 만들지 않고 부모생성자가 메인값을 받아야 하는데
// 부모에게서 받아와야하니까 자식인 너두 받아와!
super(name);
}
-----------
package class04;
class Shape{
String name;
double area;
void showInfo() {
System.out.println(this.name + " " + this.area);
}
Shape(String name){
this.name = name;
this.area = 0.0;
System.out.println("Shape의 생성자-1");
}
}
class Circle extends Shape{
int radius;
static final double PI = 3.14; // '상수' : 변하지 않는 값 / 클래스 변수 == 공유자원
// 변하지 않는 상수 값은 final로 정의 => 값에 변화를 줄 수 없음!
// 상수의 반대되는 단어 = 변수
void showInfoCircle() { //
System.out.println(this.name + " " + this.area + " " + this.radius);
}
Circle(int radius){ // 생성자 생성
super("원"); // 부모에게 기본생성자를 추가할 수도 있지만
// 설계를 바꾸는 것이기 때문에 실무에서는 쓰이지 않는다.
// -> 부모의 생성자를 사용하여 해결!
this.radius = radius;
this.area = this.radius*this.radius*PI; // 반지름 * 반지름 * 3.14
System.out.println("Circle의 생성자-1");
}
}
public class Test07 {
public static void main(String[] args) {
Circle c1 = new Circle(10);
c1.showInfo();
c1.showInfoCircle();
}
}
ex )
점 Point
x
y
void move(int x)
(1,2) -> p.move(3) -> (3,3)
void showInfo() => (0,0)
Point() -> 0.0
Point(10) -> 10,10
Point(1,2) -> 1,2
==================
색깔점 ColorPoint
x y
color
void move(int x)
void cc(String color)
void showInfoColorPoint() => pink(0,0)
ColorPoint() -> black 0,0
ColorPoint(pink) -> pink 0,0
ColorPoint(red,10,20) -> red 10,20
------내 풀이
package class04;
class Point{
int x;
int y;
void move(int x) {
this.x = x;
this.y = x;
}
void showInfo() {
System.out.println("(" + this.x + ", " + this.y + ")");
}
Point(){
this(0,0);
}
Point(int x){
this(x, x);
}
Point(int x, int y){
this.x = x;
this.y = y;
}
}
class ColorPoint extends Point{
String color;
void cc(String color) {
this.color = color;
}
void showInfoColorPoint() {
System.out.println(this.color + "(" + this.x +", " + this.y + ")");
}
ColorPoint(){
this("black", 0, 0);
}
ColorPoint(String color){
this(color, 0, 0);
}
ColorPoint(String color, int x, int y){
super(x, y);
this.color = color;
}
}
public class Test08 {
public static void main(String[] args) {
Point p = new Point();
Point p1 = new Point(10);
Point p2 = new Point(1, 2);
p.showInfo();
p1.showInfo();
p2.showInfo();
p.move(3);
p.showInfo();
System.out.println();
ColorPoint cp = new ColorPoint();
ColorPoint cp1 = new ColorPoint("pink");
ColorPoint cp2 = new ColorPoint("red", 10, 20);
cp.showInfoColorPoint();
cp1.showInfoColorPoint();
cp2.showInfoColorPoint();
cp.cc("skyblue");
cp.move(6);
cp.showInfoColorPoint();
}
}
--------------강사님 풀이(는 위랑 동일..하지만 오버라이딩을 한 후의 코드)
package class04;
class Point{
int x;
int y;
void move(int x) {
this.x = x;
this.y = x;
}
void showInfo() {
System.out.println("(" + this.x + ", " + this.y + ")");
}
Point(){
this(0,0);
}
Point(int x){
this(x, x);
}
Point(int x, int y){
this.x = x;
this.y = y;
}
}
class ColorPoint extends Point{
String color;
void cc(String color) {
this.color = color;
}
void showInfo() { // 함수 재정의(오버라이딩)
System.out.println(this.color + "(" + this.x +", " + this.y + ")");
}
ColorPoint(){
this("black", 0, 0);
}
ColorPoint(String color){
this(color, 0, 0);
}
ColorPoint(String color, int x, int y){
super(x, y);
this.color = color;
}
}
public class Test08 {
public static void main(String[] args) {
Point p = new Point();
Point p1 = new Point(10);
Point p2 = new Point(1, 2);
p.showInfo();
p1.showInfo();
p2.showInfo();
p.move(3);
p.showInfo();
System.out.println();
ColorPoint cp = new ColorPoint();
ColorPoint cp1 = new ColorPoint("pink");
ColorPoint cp2 = new ColorPoint("red", 10, 20);
cp.showInfo();
cp1.showInfo();
cp2.showInfo();
cp.cc("skyblue");
cp.move(6);
cp.showInfo();
}
}
-----------강사님께서 보여주신 예시
package class04;
class A{
void func1() {
System.out.println("A");
}
}
class B extends A{
// 상속관계에서 함수 재정의를 허용
// [오버라이딩]
// 인자의 개수,자료형 모두 같아야만한다!
void func1() {
System.out.println("B");
}
}
public class Test09 {
// [오버로딩]
// 상속관계xxx
// 함수명 중복정의->인자의 개수,자료형 달라야만했다!
public static void main(String[] args) {
A a=new A();
B b=new B();
a.func1();
b.func1();
}
}
- cp.showInfo()로 정의 내리면 빨간줄도 안쳐지고, 원하는 것이 잘 출력
[ 오버로딩 ]
>> 함수명 중복정의(오버로딩)는 인자의 개수, 자료형이 달라야만 한다.
[ 오버라이딩 ]
>> 하지만 상속관계에서 함수 재정의를 허용한다!
=> 오버라이딩
>> 인자의 개수, 자료형 모두 같아야만 한다!!
ex )
객체지향언어에서 주어가 누구냐에 따라 수행되는 것이 다른 경우가 있었다.
사람이 인사를 할 때, 안녕하세요~
하지만 학생이 인사를 할 때 Hi~ 할로! 라고 한다고 가정해보자
>> 이처럼 그 의미를 담고있지만 나는 이것도 추가하고싶어!(이 의미를 드러내고싶어!)
라고 한다면 같은 이름으로 재정의하여 출력!
>> 그 의미가 바로 오버라이딩!!!
>>객체를 넣어두고 쓰고 있었는데 빨간 줄이 뜨지 않는다.
그 이유는 자동으로 Object를 통해서 호출되고 있었기 때문이다!
>> 최상위 Object가 숨겨져 있었다!!
-------------
Object 오버라이딩 방법
package class04;
// 최상위 클래스 Object
class Book extends Object{
@Override
public String toString() {
return "책입니다!";
}
// 함수 재정의
// 오버라이딩
}
public class Test10 {
public static void main(String[] args) {
Book b = new Book();
System.out.println(b.toString());
}
}
------------------오버라이딩 예시
package class04;
class Person{
String name;
void hello() {
System.out.println("안녕하세요!");
}
Person(String name){
this.name = name;
}
}
class Student extends Person{
int score;
void hello() { // 함수 재정의 == 오버라이딩
System.out.println(">ㅂ</ ~하이!");
}
Student(String name, int score){
super(name);
this.score=score;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.name + "학생 : " + this.score + "점";
}
}
public class Test11 {
public static void main(String[] args) {
Student s = new Student("아무무", 100);
s.hello();
}
}
'디바이스 융합 자바(Java)기반 풀스택 개발자 양성과정(수업내용)' 카테고리의 다른 글
디바이스 융합 자바(Java) day12 - 동적바인딩(본인우선찾기),추상클래스,추상메서드 (0) | 2022.06.22 |
---|---|
디바이스 융합 자바(Java) day11 - toString,instanceof,포켓몬 (0) | 2022.06.21 |
디바이스 융합 자바(Java) day08 - 힙,스택,this.,this(),인스턴스 변수,클래스 변수, (0) | 2022.06.16 |
디바이스 융합 자바(Java) day07 - 함수 모듈화,객체지향 프로그래밍,오버로딩,this. (0) | 2022.06.15 |
디바이스 융합 자바(Java) day06 - 함수,오버로딩 (0) | 2022.06.14 |