Default metod java 8 ilə yeni gələn özəlliklərdən biridir. Default metod interface`in daxilində default açar sözü ilə tanımlanan və gövdəsi olan metoddur. Interface`i implements edən classların default metodu override etmək kimi bir məcburiyyəti yoxdur. Classların sərbəst seçimi var, istəsə override edə bilər, istəməsə yox. Əgər override etməsə, o zaman interface`də tanımlanan default metod istifadə ediləcəkdir. Sintaksisi aşağıdakı kimidir:
public interface DefaultMethod {
public int getCount();
public default int getNumber(){
return 7;
}
public default void showNumber(); // DOES NOT COMPILE
public String getName(){ // DOES NOT COMPILE
return "Ülvi";
}
}
Default metodlar üçün aşağıdakı qaydalar mövcuddur:
- Default metod ancaq interface daxilində elan edilə bilər, class və abstract class daxilində elan edilə bilməz;
- Default metodlar
defaultaçar sözü ilə işarələnməlidir və əgərdefaultaçar sözü ilə işarələnibsə, mütləq gövdəsi olmalıdır; - Default metodların
static,finalvə yaabstractolduğu fərz edilməməlidir (daha dəqiq desək default metodlarla bu açar sözlərin birgə istifadəsinə icazə verilmir), onlar interface`iimplementsedən class tərəfindən istifadə edilə və ya override oluna bilər; - Bütün interface metodları kimi
defaultmetodların dapublicolduğu fərz edilməlidir. Və bu səbəbdənprivatevə yaprotectedkimi işarələnəndefaultmetodlar compile olunmur.
Əgər hər hansı bir interface, daxilində default metod olan başqa bir interface`i extends edərsə, həmin default metod ilə bir neçə cür davrana bilər:
defaultmetodla bağlı hər hansı bir davranışdan imtina edə bilər, bu zaman originaldefaultmetod üçün tanımlanmış gövdə istifadə olunur;defaultmetodu yenidən override edə bilər;defaultmetodu yenidənabstractmetod kimi tanımlaya bilər. Belə olduqda isə artıq ikinci interface`iimplementsedən class həmin metodu override etmək məcburiyyətindədir.
Nümunə:
public interface HasFins {
default int getInt() {
return 1;
}
public default double getDouble() {
return 2;
}
default public boolean getBoolean() {
return true;
}
}
interface SharkFamily extends HasFins {
int getInt();
default double getDouble() {
return 5;
}
}
class TestHasFins implements HasFins { }
class TestSharkFamily implements SharkFamily {
TestSharkFamily() {
System.out.println(getDouble()); // 5.0
}
public int getInt() {
return 7;
}
public static void main(String args[]) {
new TestSharkFamily();
}
}
Interface’in default metodlarını həmin interface’i implements edən konkret class daxilində super açar sözü ilə çağırmaq mümkün deyil. super açar sözü ancaq classlar üçün istifadə edildikdə düzgün işləyir. Əgər default metodlar üçün istifadə etmək istəyiriksə, mütləq super açar sözünün qarşısında həmin interface’in adını qeyd etmək lazımdır:
interface Walk {
public default int getSpeed() {
return 10;
}
}
abstract class Animal {
public String getColor(){
return "black";
}
}
class Cat extends Animal implements Walk {
public Cat() {
System.out.println(this.getColor());
System.out.println(super.getColor());
System.out.println(this.getSpeed());
System.out.println(super.getSpeed()); // DOES NOT COMPILE
System.out.println(Walk.super.getSpeed());
}
}
MyExamCloud’da suallardan birində maraqlı bir faktla qarşılaşmışdım. Deməli, faktda qeyd olunurdu ki, siz interface’də default metodları java.lang.Object classına aid (final olmayan) hər hansı bir metodu override etmək üçün istifadə edə bilməzsiniz, əks halda compile xətası alacaqsınız:
interface A {
int groupID = 10;
default boolean equals(Object obj) { // DOES NOT COMPILE
return this.groupID == ((A) obj).groupID;
}
static void print() {
System.out.println("A");
}
}
Default Methods and Multiple Inheritance
Əvvəlki mövzulardan birində qeyd etdik ki, hər hansı bir class tərəfindən implements olunan interface`lərdə eyni abstract metodlar olarsa, problemsiz compile olunur, çünki dublikat metodlar sayılır. Amma default metodlarla vəziyyət nisbətən fərqlidir. Compiler eyni default metodlar aşkarladıqda xəta verir:
interface Walk {
public default int getSpeed() { return 10; }
}
interface Run {
public default int getSpeed() { return 20; }
}
public class Cat implements Walk, Run { // DOES NOT COMPILE
public static void main(String[] args){
System.out.println(new Cat().getSpeed());
}
}
Bu nümunədə Cat classı iki eyni default metodu (getSpeed()) irs alır, amma təyin edə bilmir ki, hansı metodu istifadə etməlidir, 10 çap olunmalıdı ya 20 ?! Ona görə də compiler belə konfliktlə rastlaşdıqda xəta verir. Amma burada bir istisna var: əgər subclass konflikt yaradan default metodu (getSpeed()) override etsə, o zaman bu kod heç bir problem olmadan compile olunacaqdır:
public class Cat implements Walk, Run {
public int getSpeed(){ return 30; }
public static void main(String[] args){
System.out.println(new Cat().getSpeed()); // 30
}
}
[topics lang=az]
