2020. 6. 14. 16:56ㆍJava
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
|
public class Ex {
public static void main(String[] args) {
/*
* 상수
* - 변하지 않는 데이터(변수)
* - 보통 클래스 내에서 상수를 선언할 때 public static final 형태로 선언
* 1) public : 어느 클래스에서나 접근 가능
* 2) static : 클래스 로딩 시 함께 로딩되어 인스턴스 생성과 무관함
* => 클래스명만으로 접근하며, 모든 인스턴스가 변수 데이터 공유
* 3) final : 데이터 변경 불가 = 상수
*/
CarInfo ci = new CarInfo();
ci.setCompany("HYUNDAI");
ci.setModelName("SONATA");
ci.setColor("CREAM WHITE");
ci.setGearType(1);
if(ci.getCompany() == "HYUNDAI") {
System.out.println("현대자동차입니다!");
} else {
System.out.println("현대자동차가 아닙니다!");
}
if(ci.getModelName() == "Sonata") {
System.out.println("쏘나타입니다!");
} else {
System.out.println("쏘나타가 아닙니다!");
}
System.out.println("==============================");
CarInfo ci2 = new CarInfo();
// 상수가 제공되는 클래스 사용 시
// 클래스명.상수명 형태를 사용하여 데이터를 쉽게 선택할 수 있음
// => ex) 문자열 데이터를 int형 파라미터로 전달해야하는 경우 상수 선택 시 혼란 X
ci2.setCompany(CarInfo.COMPANY_HYUNDAI);
if(ci2.getCompany() == CarInfo.COMPANY_HYUNDAI) {
System.out.println("현대자동차입니다!");
} else {
System.out.println("현대자동차가 아닙니다!");
}
ci2.setModelName(CarInfo.MODEL_NAME_GRANDURE);
switch (ci2.getModelName()) {
case CarInfo.MODEL_NAME_AVANTE:
System.out.println("아반떼!");
break;
case CarInfo.MODEL_NAME_SONATA:
System.out.println("쏘나타!");
break;
case CarInfo.MODEL_NAME_GRANDURE:
System.out.println("그랜져!");
break;
default:
System.out.println("잘못된 차량명!");
}
ci2.setColor(CarInfo.COLOR_PERFECT_BLACK);
ci2.setGearType(CarInfo.GEAR_TYPE_MANUAL);
System.out.println("=================================");
Calendar cal = Calendar.getInstance();
System.out.println(cal.get(Calendar.YEAR));
}
}
class CarInfo {
private String company;
private String modelName;
private String color;
private int gearType;
// -----------------------------------------------------------
// 특정 클래스 내에서 사용되는 데이터를 상수로 제공하면
// 문자열의 오타나, 정수형 파라미터 사용 시의 어려움 등을 해결할 수 있다
// => 주로 상수는 public static final 키워드를 사용하여 선언함
// => public 에 의해 어디서든 접근이 가능하며,
// static 에 의해 클래스명만으로 인스턴스 생성없이 접근할 수 있고,
// final 에 의해 데이터가 유지됨
public static final String COMPANY_HYUNDAI = "HYUNDAI";
public static final String COMPANY_KIA = "KIA";
public static final String COMPANY_DAEWOO = "DAEWOO";
public static final String MODEL_NAME_SONATA = "SONATA";
public static final String MODEL_NAME_AVANTE = "AVANTE";
public static final String MODEL_NAME_GRANDURE = "GRANDURE";
public static final String COLOR_CREAM_WHITE = "1234567";
public static final String COLOR_PERFECT_BLACK = "3333333";
public static final String COLOR_SKYBLUE = "7777777";
public static final int GEAR_TYPE_AUTO = 1;
public static final int GEAR_TYPE_MANUAL = 2;
// -----------------------------------------------------------
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getModelName() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName = modelName;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getGearType() {
return gearType;
}
public void setGearType(int gearType) {
this.gearType = gearType;
}
}
public class Ex2 {
public static void main(String[] args) {
/*
* 인터페이스(Interface)
* - 클래스가 아님 => 선언부에 class 가 아닌 interface 키워드를 사용
* - 인터페이스가 가질 수 있는 요소
* 1) 상수(public static final)
* 2) 추상메서드(public abstract)
* => 생성자나 그 외의 것들은 가질 수 없음
* - 객체 생성이 불가능. 상속 전용
* => 대신, 참조형 타입으로 사용 가능하며, 다형성 활용 가능
* - 서브클래스에서 인터페이스를 상속받을 때, 클래스와는 달리
* extends(확장) 가 아닌 implements(구현) 키워드 사용하며
* 다중 상속(구현)이 가능
* - 인터페이끼리 상속할 경우 extends 키워드를 사용하며, 다중 상속 가능
* - 강제성 및 통일성 제공(추상메서드보다 강력한 강제성을 부여)
*
* < 인터페이스 정의 기본 문법 >
* [접근제한자] interface 인터페이스명 {
* // 상수
* // 추상메서드
* }
*/
// 동물 동물 = new 동물(); // 인터페이스도 인스턴스 생성이 불가능
고래상어 고래상어 = new 고래상어();
고래상어.번식();
}
}
// 인터페이스 정의 => class 키워드가 아닌 interface 키워드 사용
interface 동물 {
// 인터페이스 내의 모든 메서드는 추상메서드
// public abstract void 번식(); // 추상메서드
// void 번식() {} // 오류 발생! 추상메서드이므로 바디{} 를 가질 수 없음!
void 번식(); // 추상메서드 = public abstract 생략되어 있음
}
// interface 를 상속받는 서브인터페이스 정의 시 extends 키워드를 사용
// => 즉, 인터페이스끼리는 상속(extends)이 가능하며, 다중 상속도 가능
interface 고래 extends 동물 {}
interface 상어 extends 동물 {}
// interface 를 상속받는 서브클래스 정의 시 extends 키워드가 아닌 implements 키워드를 사용
// => 즉, 클래스는 인터페이스를 구현(implements)하며, 다중 구현도 가능
class 고래상어 implements 고래, 상어 { // 고래, 상어 인터페이스를 동시에 구현 = 다중 구현
// 인터페이스 내에서는 슈퍼클래스(인터페이스)의 모든 메서드가 추상메서드이므로
// 중복되는 메서드에 대한 구별없이 직접 오버라이딩하여 구현하면 되기 때문에
// 중복된 메서드로 인한 혼란이 없음(= 다이아몬드 상속에서의 문제점이 발생하지 않음)
@Override
public void 번식() {
System.out.println("알을 낳아 번식!");
}
}
// ================== 다이아몬드 상속에서의 문제점 ========================
//abstract class 동물 {
// public abstract void 번식();
//}
//
//class 상어 extends 동물 {
//
// @Override
// public void 번식() {
// System.out.println("알을 낳아 번식!");
// }
//
//}
//
//class 고래 extends 동물 {
//
// @Override
// public void 번식() {
// System.out.println("새끼를 낳아 번식!");
// }
//
//}
//
//// 자바에서의 상속은 단일 상속만 가능하다! => 두 개 이상의 클래스로부터 다중 상속 불가!
//class 고래상어 extends 상어, 고래 {
// // 상어, 고래 클래스가 공통으로 가지고 있는 번식() 메서드를 호출했을 때
// // 어느 객체의 번식() 메서드를 호출해야하는지가 분명하지 않게 되기 때문에 다중 상속 금지
//}
// 인터페이스 정의
// class 대신 interface 키워드 사용
public interface MyInterface {
// 인터페이스 내의 멤버변수 : 모두 상수(public static final)로 취급됨
public static final int MEMBER1 = 10; // 상수
int MEMBER2 = 20; // 상수 = public static final 생략되어 있음
// 인터페이스 내의 멤버메서드 : 모두 추상메서드(public abstract) 로 취급됨
public abstract void method1(); // 추상메서드
void method2(); // 추상메서드 = public abstract 생략되어 있음
}
public class Test2 {
public static void main(String[] args) {
// SuperMan, Bird, Airplane 인스턴스 생성 후 각 메서드 호출
SuperMan s = new SuperMan();
s.takeOff();
s.fly();
s.land();
Bird b = new Bird();
b.takeOff();
b.fly();
b.land();
Airplane a = new Airplane();
a.takeOff();
a.fly();
a.land();
System.out.println("--------------------");
// 인터페이스의 업캐스팅을 통한 다형성 활용
// SuperMan, Bird, Airplane 인스턴스를 Flyer 인터페이스 타입으로 업캐스팅 하여
// 공통된 변수를 통해 공통된 메서드를 호출 가능 = 코드의 통일성 제공
Flyer f;
f = new SuperMan(); // 업캐스팅
f.takeOff();
f.fly();
f.land();
f = new Bird(); // 업캐스팅
f.takeOff();
f.fly();
f.land();
f = new Airplane(); // 업캐스팅
f.takeOff();
f.fly();
f.land();
System.out.println("---------------------");
// 다형성 활용 2. Flyer 타입 배열 사용
Flyer[] flyers = {new SuperMan(), new Bird(), new Airplane()};
// for문을 사용하여 각 배열 요소의 인스턴스에 있는 메서드 3개 호출
// for(int i = 0; i < flyers.length; i++) {
// Flyer flyer = flyers[i];
// flyer.takeOff();
// flyer.fly();
// flyer.land();
// }
for(Flyer flyer : flyers) {
flyer.takeOff();
flyer.fly();
flyer.land();
}
}
}
// Flyer 인터페이스 정의
// 추상메서드 3개 정의
// 1) 이륙(takeOff()) - 파라미터 없음, 리턴값 없음
// 2) 비행(fly()) - 파라미터 없음, 리턴값 없음
// 3) 착륙(land()) - 파라미터 없음, 리턴값 없음
interface Flyer {
public abstract void takeOff();
public abstract void fly();
public abstract void land();
}
// SuperMan 클래스 정의 - Flyer 인터페이스 구현
// takeOff() : "SuperMan 이륙!", fly() : "SuperMan 비행!", land() : "SuperMan 착륙!"
class SuperMan implements Flyer {
@Override
public void takeOff() {
System.out.println("SuperMan 이륙!");
}
@Override
public void fly() {
System.out.println("SuperMan 비행!");
}
@Override
public void land() {
System.out.println("SuperMan 착륙!");
}
}
// Bird 클래스 정의 - Flyer 인터페이스 구현
// takeOff() : "Bird 이륙!", fly() : "Bird 비행!", land() : "Bird 착륙!"
class Bird implements Flyer {
@Override
public void takeOff() {
System.out.println("Bird 이륙!");
}
@Override
public void fly() {
System.out.println("Bird 비행!");
}
@Override
public void land() {
System.out.println("Bird 착륙!");
}
}
// Airplane 클래스 정의 - Flyer 인터페이스 구현
// takeOff() : "Airplane 이륙!", fly() : "Airplane 비행!", land() : "Airplane 착륙!"
class Airplane implements Flyer {
@Override
public void takeOff() {
System.out.println("Airplane 이륙!");
}
@Override
public void fly() {
System.out.println("Airplane 비행!");
}
@Override
public void land() {
System.out.println("Airplane 착륙!");
}
}
public class Test3 {
public static void main(String[] args) {
// 삼성TV 인스턴스 생성
삼성TV s = new 삼성TV();
s.channelChange(99);
s.channelUp();
s.channelUp();
s.channelDown();
s.volumeUp();
s.volumeDown();
s.volumeDown();
s.bixby();
System.out.println("-----------");
엘지TV l = new 엘지TV();
l.channelChange(99);
l.channelUp();
l.channelUp();
l.channelDown();
l.volumeUp();
l.volumeDown();
l.volumeDown();
l.thinQ();
System.out.println("===================");
// 다형성 활용 = 만능리모콘
Tv 만능리모콘 = new 삼성TV();
만능리모콘.channelUp();
만능리모콘.channelDown();
만능리모콘.volumeUp();
만능리모콘.volumeDown();
// 만능리모콘.bixby(); // 업캐스팅(만능리모콘) 시 사용 불가
만능리모콘 = new 엘지TV();
만능리모콘.channelUp();
만능리모콘.channelDown();
만능리모콘.volumeUp();
만능리모콘.volumeDown();
// 만능리모콘.thinQ(); // 업캐스팅(만능리모콘) 시 사용 불가
System.out.println("===============================");
if(만능리모콘 instanceof 엘지TV) {
엘지TV 엘지리모콘 = (엘지TV) 만능리모콘;
엘지리모콘.channelChange(99);
엘지리모콘.channelUp();
엘지리모콘.channelUp();
엘지리모콘.channelDown();
엘지리모콘.volumeUp();
엘지리모콘.volumeDown();
엘지리모콘.volumeDown();
엘지리모콘.thinQ();
}
}
}
// Channel 인터페이스 정의
interface IChannel {
// 채널 변경에 필요한 메서드 3개 정의
public abstract void channelUp();
public abstract void channelDown();
public abstract void channelChange(int channel);
}
// Volume 인터페이스 정의
interface IVolume {
// 채널 변경에 필요한 메서드 2개 정의
public abstract void volumeUp();
public abstract void volumeDown();
}
// Tv 클래스 정의 => IChannel, IVolume 인터페이스 상속(구현)
// => 추상메서드를 오버라이딩 하지 않음 => 추상클래스로 정의
abstract class Tv implements IChannel, IVolume {
// 멤버변수 선언
private boolean isPowerOn; // 전원
private int channel, volume; // 채널, 볼륨
private final int maxChannel, minChannel, maxVolume, minVolume; // 최대/최소 전원, 볼륨
// => blank final 상수이므로 직접 초기화하지 않으려면, 생성자에서 초기화 필수!
// 파라미터 6개를 전달받아 초기화하는 생성자 Tv() 정의(전원 제외)
public Tv(int channel, int volume, int maxChannel, int minChannel,
int maxVolume, int minVolume) {
super();
this.channel = channel;
this.volume = volume;
this.maxChannel = maxChannel;
this.minChannel = minChannel;
this.maxVolume = maxVolume;
this.minVolume = minVolume;
}
public boolean isPowerOn() {
return isPowerOn;
}
public void changePower() {
// 전원 버튼을 누르면 현재 전원 상태를 반전시킴
isPowerOn = !isPowerOn;
}
public int getChannel() {
return channel;
}
public void setChannel(int channel) {
this.channel = channel;
}
public int getVolume() {
return volume;
}
public void setVolume(int volume) {
this.volume = volume;
}
public int getMaxChannel() {
return maxChannel;
}
public int getMinChannel() {
return minChannel;
}
public int getMaxVolume() {
return maxVolume;
}
public int getMinVolume() {
return minVolume;
}
}
// 삼성TV 클래스 정의
class 삼성TV extends Tv {
public 삼성TV() {
// 슈퍼클래스의 파라미터 생성자를 호출하는 생성자가 파라미터가 없어도 무관함
super(1, 0, 100, 1, 20, 0);
}
@Override
public void channelUp() {
System.out.println("삼성TV 채널 증가!");
setChannel(getChannel() + 1); // 채널 1 증가시킴
// 만약, 증가 후의 채널이 최대채널보다 클 경우 최소채널로 변경
if(getChannel() > getMaxChannel()) {
setChannel(getMinChannel());
}
System.out.println("현재채널 : " + getChannel());
}
@Override
public void channelDown() {
System.out.println("삼성TV 채널 감소!");
setChannel(getChannel() - 1); // 채널 1 감소시킴
// 만약, 감소 후의 채널이 최소채널보다 작을 경우 최대채널로 변경
if(getChannel() < getMinChannel()) {
setChannel(getMaxChannel());
}
System.out.println("현재채널 : " + getChannel());
}
@Override
public void channelChange(int channel) {
System.out.println("삼성TV 채널 전환 - " + channel);
if(channel >= getMinChannel() && channel <= getMaxChannel()) {
setChannel(channel);
}
System.out.println("현재채널 : " + getChannel());
}
@Override
public void volumeUp() {
System.out.println("삼성TV 볼륨 증가!");
setVolume(getVolume() + 1); // 볼륨 1 증가시킴
if(getVolume() > getMaxVolume()) { // 증가된 볼륨이 최대볼륨보다 크면
setVolume(getMaxVolume()); // 최대볼륨으로 고정
}
System.out.println("현재볼륨 : " + getVolume());
}
@Override
public void volumeDown() {
System.out.println("삼성TV 볼륨 감소!");
setVolume(getVolume() - 1); // 볼륨 1 감소시킴
if(getVolume() < getMinVolume()) { // 감소된 볼륨이 최소볼륨보다 작으면
setVolume(getMinVolume()); // 최소볼륨으로 고정
}
System.out.println("현재볼륨 : " + getVolume());
}
public void bixby() {
System.out.println("삼성TV 빅스비 기능!");
}
}
// 엘지TV 클래스 정의
class 엘지TV extends Tv {
public 엘지TV() {
// 슈퍼클래스의 파라미터 생성자를 호출하는 생성자가 파라미터가 없어도 무관함
super(1, 0, 150, 1, 40, 0);
}
@Override
public void channelUp() {
System.out.println("엘지TV 채널 증가!");
setChannel(getChannel() + 1); // 채널 1 증가시킴
// 만약, 증가 후의 채널이 최대채널보다 클 경우 최소채널로 변경
if(getChannel() > getMaxChannel()) {
setChannel(getMinChannel());
}
System.out.println("현재채널 : " + getChannel());
}
@Override
public void channelDown() {
System.out.println("엘지TV 채널 감소!");
setChannel(getChannel() - 1); // 채널 1 감소시킴
// 만약, 감소 후의 채널이 최소채널보다 작을 경우 최대채널로 변경
if(getChannel() < getMinChannel()) {
setChannel(getMaxChannel());
}
System.out.println("현재채널 : " + getChannel());
}
@Override
public void channelChange(int channel) {
System.out.println("엘지TV 채널 전환 - " + channel);
if(channel >= getMinChannel() && channel <= getMaxChannel()) {
setChannel(channel);
}
System.out.println("현재채널 : " + getChannel());
}
@Override
public void volumeUp() {
System.out.println("엘지TV 볼륨 증가!");
setVolume(getVolume() + 1); // 볼륨 1 증가시킴
if(getVolume() > getMaxVolume()) { // 증가된 볼륨이 최대볼륨보다 크면
setVolume(getMaxVolume()); // 최대볼륨으로 고정
}
System.out.println("현재볼륨 : " + getVolume());
}
@Override
public void volumeDown() {
System.out.println("엘지TV 볼륨 감소!");
setVolume(getVolume() - 1); // 볼륨 1 감소시킴
if(getVolume() < getMinVolume()) { // 감소된 볼륨이 최소볼륨보다 작으면
setVolume(getMinVolume()); // 최소볼륨으로 고정
}
System.out.println("현재볼륨 : " + getVolume());
}
public void thinQ() {
System.out.println("엘지TV 의 thinQ 기능!");
}
}
|
cs |
final에 대해서 배웠던 저번 시간에 이어 final을 상수로 부르고 상수의 사용법에 대해서도 배우게 되었다. 상수를 활용하여서 개발자 입장이 아니라 사용자 입장에서 프로그램을 사용할 때 어떤 변수명이 있는지 어떤 데이터 타입인지를 잘 모를 경우에 사용하기 위한 문법을 배워보았는데 public static final을 사용하여 정의해두는 것이었는데 사용자 입장이라면 아주 편할 것 같았다. 잘못 입력해서 프로그램이 인식을 못할 일도 줄어들고 시간도 절약해주는 고마운 문법이라고 느껴졌다. 역시 이것 또한 복습을 좀 더 해서 확실히 개념을 내 것으로 만들어 두어야겠다고 느꼈다. 그리고 인터페이스(interface)에 대해서도 배우게 되었는데 상속과 달리 extends를 사용하지 않고 implements를 사용한다는 것이 일단 눈에 보이는 큰 차이점이었고 내부적으로는 생성자나 다른 메서드는 사용하지 못하고 상수와 추상 메서드만이 정의 가능하였고 인터페이스를 구현받아 사용하는 클래스에서는 어느 정도 사용을 강제당하며 프로그램의 통일성을 추구하는 문법이었고 역시 상속과 비슷한 면이 많다고 느껴졌다. interface를 정의할 경우 자동으로 상수 취급과 추상 메서드 취급이 되어버리기 때문에 상수의 경우에는 public static final이 생략되어 있어서 데이터 타입과 변수명만 작성하면 자동으로 상수 취급이 되고 메서드의 경우에도 public abstract 가 자동 생략되어 void 메서드명만 적어도 자동으로 추상 메서드 취급이 된다는 점이 특이점이었다. 이게 헷갈릴 수 있으니 개념을 잘 다져야 할 것 같다. 나머지는 테스트 클래스로 배운 상수와 인터페이스를 활용해서 실습을 해보았는데 확실히 해보면서 좀 더 쉽게 와 닿고 이렇게 사용되어지는구나라고 느낄 수 있었다. 개발자는 공부만 마냥 하는 것보단 확실히 키보드를 두드려봐야 내 것으로 만들어진다는 게 좋은 거 같다.
'Java' 카테고리의 다른 글
Java - toString(),equals() (0) | 2020.06.27 |
---|---|
Java - 인터페이스, 마커(Marker) (0) | 2020.06.14 |
Java - 추상화,final (0) | 2020.06.14 |
Java - instanceof (0) | 2020.06.14 |
Java - super(),업캐스팅,다운캐스팅 (0) | 2020.06.14 |