Her ne kadar, Polimorfizm bu yazıda çok ayrıntılı olarak açıklanmıştır, ancak bunun neden bir kısmına daha fazla vurgu yapmak istiyorum.
Polimorfizm herhangi bir OOP dilinde neden bu kadar önemlidir?
Miras / Polimorfizm olan ve olmayan bir TV için basit bir uygulama oluşturmaya çalışalım. Uygulamanın her sürümünü yayınlayın, küçük bir retrospektif yapıyoruz.
Diyelim ki, bir TV şirketinde yazılım mühendisisiniz ve kullanıcı komutunda değerlerini artırmak ve azaltmak için Ses Düzeyi, Parlaklık ve Renk denetleyicileri için yazılım yazmanız isteniyor.
Bu özelliklerin her biri için sınıflar ekleyerek
- set: - Bir denetleyicinin değerini ayarlamak için (varsayalım ki denetleyiciye özel kod var)
- get: - Bir denetleyicinin değerini almak için (varsayalım ki denetleyiciye özel kod var)
- ayarlayın: - Girişi doğrulamak ve bir denetleyici ayarlamak için. (Genel doğrulamalar .. denetleyicilerden bağımsız olarak)
- kontrolörler ile kullanıcı giriş eşlemesi: - Kullanıcı girişini ve kontrolörleri buna göre çağırmak için.
Uygulama Sürümü 1
import java.util.Scanner;
class VolumeControllerV1 {
private int value;
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of VolumeController \t"+this.value);
this.value = value;
System.out.println("New value of VolumeController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class BrightnessControllerV1 {
private int value;
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of BrightnessController \t"+this.value);
this.value = value;
System.out.println("New value of BrightnessController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class ColourControllerV1 {
private int value;
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of ColourController \t"+this.value);
this.value = value;
System.out.println("New value of ColourController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
/*
* There can be n number of controllers
* */
public class TvApplicationV1 {
public static void main(String[] args) {
VolumeControllerV1 volumeControllerV1 = new VolumeControllerV1();
BrightnessControllerV1 brightnessControllerV1 = new BrightnessControllerV1();
ColourControllerV1 colourControllerV1 = new ColourControllerV1();
OUTER: while(true) {
Scanner sc=new Scanner(System.in);
System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
System.out.println("Press any other Button to shutdown");
int button = sc.nextInt();
switch (button) {
case 1: {
volumeControllerV1.adjust(5);
break;
}
case 2: {
volumeControllerV1.adjust(-5);
break;
}
case 3: {
brightnessControllerV1.adjust(5);
break;
}
case 4: {
brightnessControllerV1.adjust(-5);
break;
}
case 5: {
colourControllerV1.adjust(5);
break;
}
case 6: {
colourControllerV1.adjust(-5);
break;
}
default:
System.out.println("Shutting down...........");
break OUTER;
}
}
}
}
Artık dağıtılmaya hazır ilk çalışma uygulamamız var. Şimdiye kadar yapılan çalışmaları analiz etme zamanı.
TV Uygulama Sürümü 1
- Ayarlama (int değeri) kodu her üç sınıfta da yinelenir. Kod yinelenmesini en aza indirmek istiyorsunuz. (Ancak ortak kodu düşünmediniz ve yinelenen kodlardan kaçınmak için bazı süper sınıfa taşıdınız)
Başvurunuz beklendiği gibi çalıştığı sürece bununla yaşamaya karar verdiniz.
Bazen patronunuz size geri döner ve mevcut uygulamaya sıfırlama işlevselliği eklemenizi ister. Sıfırla, üç denetleyicinin üçünü de kendi varsayılan değerlerine ayarlar.
Yeni işlevsellik için yeni bir sınıf (ResetFunctionV2) yazmaya başlarsınız ve bu yeni özellik için kullanıcı giriş eşleme kodunu eşlersiniz.
Uygulama Sürümü 2
import java.util.Scanner;
class VolumeControllerV2 {
private int defaultValue = 25;
private int value;
int getDefaultValue() {
return defaultValue;
}
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of VolumeController \t"+this.value);
this.value = value;
System.out.println("New value of VolumeController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class BrightnessControllerV2 {
private int defaultValue = 50;
private int value;
int get() {
return value;
}
int getDefaultValue() {
return defaultValue;
}
void set(int value) {
System.out.println("Old value of BrightnessController \t"+this.value);
this.value = value;
System.out.println("New value of BrightnessController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class ColourControllerV2 {
private int defaultValue = 40;
private int value;
int get() {
return value;
}
int getDefaultValue() {
return defaultValue;
}
void set(int value) {
System.out.println("Old value of ColourController \t"+this.value);
this.value = value;
System.out.println("New value of ColourController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class ResetFunctionV2 {
private VolumeControllerV2 volumeControllerV2 ;
private BrightnessControllerV2 brightnessControllerV2;
private ColourControllerV2 colourControllerV2;
ResetFunctionV2(VolumeControllerV2 volumeControllerV2, BrightnessControllerV2 brightnessControllerV2, ColourControllerV2 colourControllerV2) {
this.volumeControllerV2 = volumeControllerV2;
this.brightnessControllerV2 = brightnessControllerV2;
this.colourControllerV2 = colourControllerV2;
}
void onReset() {
volumeControllerV2.set(volumeControllerV2.getDefaultValue());
brightnessControllerV2.set(brightnessControllerV2.getDefaultValue());
colourControllerV2.set(colourControllerV2.getDefaultValue());
}
}
/*
* so on
* There can be n number of controllers
*
* */
public class TvApplicationV2 {
public static void main(String[] args) {
VolumeControllerV2 volumeControllerV2 = new VolumeControllerV2();
BrightnessControllerV2 brightnessControllerV2 = new BrightnessControllerV2();
ColourControllerV2 colourControllerV2 = new ColourControllerV2();
ResetFunctionV2 resetFunctionV2 = new ResetFunctionV2(volumeControllerV2, brightnessControllerV2, colourControllerV2);
OUTER: while(true) {
Scanner sc=new Scanner(System.in);
System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
int button = sc.nextInt();
switch (button) {
case 1: {
volumeControllerV2.adjust(5);
break;
}
case 2: {
volumeControllerV2.adjust(-5);
break;
}
case 3: {
brightnessControllerV2.adjust(5);
break;
}
case 4: {
brightnessControllerV2.adjust(-5);
break;
}
case 5: {
colourControllerV2.adjust(5);
break;
}
case 6: {
colourControllerV2.adjust(-5);
break;
}
case 7: {
resetFunctionV2.onReset();
break;
}
default:
System.out.println("Shutting down...........");
break OUTER;
}
}
}
}
Böylece uygulamanızı Sıfırla özelliği ile hazır hale getirirsiniz. Ama şimdi bunu fark etmeye başlıyorsun
TV Uygulaması Sürüm 2'deki sorunlar
- Ürüne yeni bir denetleyici eklendiğinde, Özellik kodunu sıfırla seçeneğini değiştirmeniz gerekir.
- Denetleyicinin sayısı çok yükselirse, denetleyicilerin referanslarını tutma konusunda sorun yaşarsınız.
- Sıfırlama özellik kodu, tüm denetleyiciler Sınıfının koduyla (varsayılan değerleri almak ve ayarlamak için) sıkıca bağlıdır.
- Sıfırlama özellik sınıfı (ResetFunctionV2), Controller sınıfının (ayar) istenmeyen diğer yöntemlerine erişebilir.
Aynı zamanda, Patronunuzdan, her kontrol cihazının, başlangıçta, şirketin internet üzerinden barındırılan sürücü deposundan sürücünün en son sürümünü kontrol etmesi gereken bir özellik eklemeniz gerekebileceğini duyuyorsunuz.
Şimdi eklenecek bu yeni özelliğin Sıfırlama özelliğine benzediğini düşünmeye başlıyorsunuz ve uygulamanızı yeniden hesaba katmazsanız Uygulama Sorunları (V2) çarpılacaktır.
Kalıtım kullanmayı düşünmeye başlarsınız, böylece JAVA'nın polimorfik yeteneğinden yararlanabilirsiniz ve yeni bir soyut sınıf (ControllerV3) eklersiniz.
- Get and set yönteminin imzasını bildirin.
- Daha önce tüm denetleyiciler arasında çoğaltılan ayarlama yöntemi uygulamasını içerir.
- Polimorfizmden yararlanarak sıfırlama özelliğinin kolayca uygulanabilmesi için setDefault yöntemini bildirin.
Bu geliştirmelerle TV uygulamanızın 3. versiyonunu yanınızda hazır hale getireceksiniz.
Uygulama Sürümü 3
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
abstract class ControllerV3 {
abstract void set(int value);
abstract int get();
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
abstract void setDefault();
}
class VolumeControllerV3 extends ControllerV3 {
private int defaultValue = 25;
private int value;
public void setDefault() {
set(defaultValue);
}
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of VolumeController \t"+this.value);
this.value = value;
System.out.println("New value of VolumeController \t"+this.value);
}
}
class BrightnessControllerV3 extends ControllerV3 {
private int defaultValue = 50;
private int value;
public void setDefault() {
set(defaultValue);
}
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of BrightnessController \t"+this.value);
this.value = value;
System.out.println("New value of BrightnessController \t"+this.value);
}
}
class ColourControllerV3 extends ControllerV3 {
private int defaultValue = 40;
private int value;
public void setDefault() {
set(defaultValue);
}
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of ColourController \t"+this.value);
this.value = value;
System.out.println("New value of ColourController \t"+this.value);
}
}
class ResetFunctionV3 {
private List<ControllerV3> controllers = null;
ResetFunctionV3(List<ControllerV3> controllers) {
this.controllers = controllers;
}
void onReset() {
for (ControllerV3 controllerV3 :this.controllers) {
controllerV3.setDefault();
}
}
}
/*
* so on
* There can be n number of controllers
*
* */
public class TvApplicationV3 {
public static void main(String[] args) {
VolumeControllerV3 volumeControllerV3 = new VolumeControllerV3();
BrightnessControllerV3 brightnessControllerV3 = new BrightnessControllerV3();
ColourControllerV3 colourControllerV3 = new ColourControllerV3();
List<ControllerV3> controllerV3s = new ArrayList<>();
controllerV3s.add(volumeControllerV3);
controllerV3s.add(brightnessControllerV3);
controllerV3s.add(colourControllerV3);
ResetFunctionV3 resetFunctionV3 = new ResetFunctionV3(controllerV3s);
OUTER: while(true) {
Scanner sc=new Scanner(System.in);
System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
int button = sc.nextInt();
switch (button) {
case 1: {
volumeControllerV3.adjust(5);
break;
}
case 2: {
volumeControllerV3.adjust(-5);
break;
}
case 3: {
brightnessControllerV3.adjust(5);
break;
}
case 4: {
brightnessControllerV3.adjust(-5);
break;
}
case 5: {
colourControllerV3.adjust(5);
break;
}
case 6: {
colourControllerV3.adjust(-5);
break;
}
case 7: {
resetFunctionV3.onReset();
break;
}
default:
System.out.println("Shutting down...........");
break OUTER;
}
}
}
}
Her ne kadar V2 sayı listesinde listelenen Sorunun çoğu hariç
TV Uygulaması Sürüm 3'teki Sorunlar
- Sıfırlama özelliği sınıfı (ResetFunctionV3), Controller sınıfının (ayar) istenmeyen diğer yöntemlerine erişebilir.
Yine, bu sorunu çözmeyi düşünüyorsunuz, çünkü şimdi uygulamak için başka bir özelliğiniz (başlangıçta sürücü güncellemesi) var. Düzeltmezseniz, yeni özelliklere de kopyalanacaktır.
Yani soyut sınıfta tanımlanan sözleşmeyi bölebilir ve
- Sıfırlama özelliği.
- Sürücü güncellemesi.
Ve 1. beton sınıfınızın bunları aşağıdaki gibi uygulamasını sağlayın
Uygulama Sürümü 4
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
interface OnReset {
void setDefault();
}
interface OnStart {
void checkForDriverUpdate();
}
abstract class ControllerV4 implements OnReset,OnStart {
abstract void set(int value);
abstract int get();
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class VolumeControllerV4 extends ControllerV4 {
private int defaultValue = 25;
private int value;
@Override
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of VolumeController \t"+this.value);
this.value = value;
System.out.println("New value of VolumeController \t"+this.value);
}
@Override
public void setDefault() {
set(defaultValue);
}
@Override
public void checkForDriverUpdate() {
System.out.println("Checking driver update for VolumeController .... Done");
}
}
class BrightnessControllerV4 extends ControllerV4 {
private int defaultValue = 50;
private int value;
@Override
int get() {
return value;
}
@Override
void set(int value) {
System.out.println("Old value of BrightnessController \t"+this.value);
this.value = value;
System.out.println("New value of BrightnessController \t"+this.value);
}
@Override
public void setDefault() {
set(defaultValue);
}
@Override
public void checkForDriverUpdate() {
System.out.println("Checking driver update for BrightnessController .... Done");
}
}
class ColourControllerV4 extends ControllerV4 {
private int defaultValue = 40;
private int value;
@Override
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of ColourController \t"+this.value);
this.value = value;
System.out.println("New value of ColourController \t"+this.value);
}
@Override
public void setDefault() {
set(defaultValue);
}
@Override
public void checkForDriverUpdate() {
System.out.println("Checking driver update for ColourController .... Done");
}
}
class ResetFunctionV4 {
private List<OnReset> controllers = null;
ResetFunctionV4(List<OnReset> controllers) {
this.controllers = controllers;
}
void onReset() {
for (OnReset onreset :this.controllers) {
onreset.setDefault();
}
}
}
class InitializeDeviceV4 {
private List<OnStart> controllers = null;
InitializeDeviceV4(List<OnStart> controllers) {
this.controllers = controllers;
}
void initialize() {
for (OnStart onStart :this.controllers) {
onStart.checkForDriverUpdate();
}
}
}
/*
* so on
* There can be n number of controllers
*
* */
public class TvApplicationV4 {
public static void main(String[] args) {
VolumeControllerV4 volumeControllerV4 = new VolumeControllerV4();
BrightnessControllerV4 brightnessControllerV4 = new BrightnessControllerV4();
ColourControllerV4 colourControllerV4 = new ColourControllerV4();
List<ControllerV4> controllerV4s = new ArrayList<>();
controllerV4s.add(brightnessControllerV4);
controllerV4s.add(volumeControllerV4);
controllerV4s.add(colourControllerV4);
List<OnStart> controllersToInitialize = new ArrayList<>();
controllersToInitialize.addAll(controllerV4s);
InitializeDeviceV4 initializeDeviceV4 = new InitializeDeviceV4(controllersToInitialize);
initializeDeviceV4.initialize();
List<OnReset> controllersToReset = new ArrayList<>();
controllersToReset.addAll(controllerV4s);
ResetFunctionV4 resetFunctionV4 = new ResetFunctionV4(controllersToReset);
OUTER: while(true) {
Scanner sc=new Scanner(System.in);
System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
int button = sc.nextInt();
switch (button) {
case 1: {
volumeControllerV4.adjust(5);
break;
}
case 2: {
volumeControllerV4.adjust(-5);
break;
}
case 3: {
brightnessControllerV4.adjust(5);
break;
}
case 4: {
brightnessControllerV4.adjust(-5);
break;
}
case 5: {
colourControllerV4.adjust(5);
break;
}
case 6: {
colourControllerV4.adjust(-5);
break;
}
case 7: {
resetFunctionV4.onReset();
break;
}
default:
System.out.println("Shutting down...........");
break OUTER;
}
}
}
}
Şimdi karşılaştığınız tüm sorunlara değinildi ve Miras ve Çok Biçimlilik kullanımı ile
- Uygulamanın çeşitli bölümlerini gevşek bir şekilde bağlı tutun. (Sıfırla veya Sürücü Güncelleme özelliği bileşenlerinin gerçek denetleyici sınıflarından (Hacim, Parlaklık ve Renk) haberdar edilmesine gerek yoktur, OnReset veya OnStart uygulayan herhangi bir sınıf Sıfırlama veya Sürücü Güncelleme özelliği için kabul edilebilir bileşenleri).
- Uygulama geliştirmesi daha kolay hale gelir.
- Soyutlama katmanını koru.
Bu yardımcı olur umarım :-)