JavaRush /Java блогу /Random-KY /Java 8деги демейки ыкмалар: Алар эмне кыла алат жана эмне...
Spitfire
Деңгээл

Java 8деги демейки ыкмалар: Алар эмне кыла алат жана эмне кыла албайт?

Группада жарыяланган
Питер Верхас 2014-жылдын апрелинде жазылган макаланын котормосу . Java 8деги демейки ыкмалар: Алар эмне кыла алат жана эмне кыла алbyte?  - 1Котормочудан: " демейки метод " термини Java-да жаңы эле пайда болду жана мен анын орус тorне котормосу бар-жокпу билбейм. Мен "демейки ыкма" деген терминди колдоном, бирок мен аны идеалдуу эмес деп эсептейм. Мен сизди ийгorктүү котормо боюнча талкуулоого чакырам.

Демейки ыкма деген эмне

Эми, Java 8дин чыгышы менен, интерфейс аны ишке ашырган класстарга шайкеш келиши үчүн интерфейстерге жаңы ыкмаларды кошо аласыз. Эгер сиз Киевден Нью-Йоркко чейин көптөгөн программисттер колдонгон китепкана иштеп жатсаңыз, бул абдан маанилүү. Java 8ге чейин, эгер сиз китепканада интерфейсти аныктасаңыз, интерфейсиңизди иштетип жаткан кээ бир тиркемелер жаңыртылганда бузулуп калуу коркунучу жок эле ага ыкмаларды кошо алган жоксуз. Демек, Java 8де мындан ары мындан коркпойсузбу? Жок болбойт. Интерфейске демейки ыкманы кошуу кээ бир класстарды жараксыз кылып коюшу мүмкүн. Келгиле, адегенде демейки ыкмалардын жакшы жактарын карап көрөлү. Java 8де ыкманы түздөн-түз интерфейсте ишке ашырууга болот. (Интерфейстеги статикалык ыкмалар эми ишке ашырылышы мүмкүн, бирок бул башка окуя.) Интерфейсте ишке ашырылган метод демейки метод деп аталат жана демейки ачкыч сөз менен белгиленет . Эгерде класс интерфейсти ишке ашырса, анда ал интерфейсте ишке ашырылган методдорду ишке ашыра алат, бирок талап кылынbyte. Класс демейки ишке ашырууну мурастайт. Ошондуктан алар ишке ашырган интерфейсти өзгөртүүдө класстарды өзгөртүүнүн кажети жок.

Бир нече тукум куучулук?

Эгерде класс бирден ашык (мисалы, эки) интерфейсти ишке ашырса жана алар бирдей демейки ыкманы ишке ашырса, иштер татаалдашат. Класс кайсы ыкманы мурастайт? Жооп эч ким эмес. Бул учурда класс методдун өзүн ишке ашырышы керек (же түз же башка класстан мурастоо жолу менен). Эгерде бир интерфейсте демейки ыкма болсо, экинчисинде ошол эле ыкма абстракттуу болсо, абал окшош. Java 8 тартиптүү болууга жана түшүнүксүз кырдаалдардан качууга аракет кылат. Эгерде методдор бир нече интерфейсте жарыя кылынса, класстын демейки ишке ашыруу эч кандай мураска алынbyte - сиз компиляция катасын аласыз. Бирок, классыңыз мурунтан эле компиляцияланган болсо, сиз компиляция катасын ала албайсыз. Java 8 бул жагынан жетиштүү бекем эмес. Мунун себептери бар, мен аларды талкуулагым келбейт (мисалы: Java релизинин мурунтан эле чыгарылганы жана талкуулоо үчүн убакыт көп убакыт өткөн жана жалпысынан бул алар үчүн орун эмес).
  • Сизде эки интерфейс бар жана класс алардын экөөнү тең ишке ашырат дейли.
  • Интерфейстердин бири демейки m() ыкмасын ишке ашырат.
  • Сиз бардык интерфейстерди жана классты түзөсүз.
  • m() методу жок интерфейсти абстракттуу ыкма катары жарыялоо менен өзгөртөсүз.
  • Сиз өзгөртүлгөн интерфейсти гана түзөсүз.
  • Класс башта.
Java 8деги демейки ыкмалар: Алар эмне кыла алат жана эмне кыла алbyte?  - 2Бул учурда класс иштейт. Аны жаңыртылган интерфейстер менен компиляциялай албайсыз, бирок ал эски versionлары менен түзүлгөн, ошондуктан иштейт. Азыр
  • абстракттуу m() ыкмасы менен интерфейсти өзгөртүп, демейки ишке киргизүүнү кошуңуз.
  • Өзгөртүлгөн интерфейсти түзүңүз.
  • Классты иштетүү: ката.
Методду демейки ишке ашырууну камсыз кылган эки интерфейс болгондо, класстын өзү тарабынан ишке ашырылмайынча, ал методду класста чакырууга болбойт (кайрадан, өз алдынча же башка класстан мураска алынган). Java 8деги демейки ыкмалар: Алар эмне кыла алат жана эмне кыла алbyte?  - 3Класс туура келет. Аны өзгөртүлгөн интерфейс менен жүктөсө болот. Ал тургай, эки интерфейсте демейки ишке ашырууга ээ ыкма чакырылмайынча иштей алат.

Мисал code

Java 8деги демейки ыкмалар: Алар эмне кыла алат жана эмне кыла алbyte?  - 4Жогорудагыларды көрсөтүү үчүн мен C.java классы үчүн тест каталогун жана I1.java жана I2.java файлдарындагы интерфейстер үчүн 3 подкаталогдорду түздүм. Сынактын түпкү каталогу C.java классынын баштапкы codeун камтыйт. Негизги каталог аткарууга жана компиляцияга ылайыктуу интерфейстердин versionсын камтыйт: I1 интерфейсинин демейки ыкмасы m(); I2 интерфейсинин азырынча эч кандай ыкмалары жок. Класста метод бар main, ошондуктан биз аны сынап көрүү үчүн аны аткара алабыз. Ал буйрук сабынын аргументтеринин бар-жоктугун текшерет, ошондуктан биз аны оңой эле аткара алабыз m().
~/github/test$ cat C.java
public class C implements I1, I2 {
  public static void main(String[] args) {
    C c = new C();
    if( args.length == 0 ){
      c.m();
    }
  }
}
~/github/test$ cat base/I1.java
public interface I1 {
  default void m(){
    System.out.println("hello interface 1");
  }
}
~/github/test$ cat base/I2.java
public interface I2 {
}
Сиз классты буйрук сабынан компиляциялап, иштете аласыз.
~/github/test$ javac -cp .:base C.java
~/github/test$ java -cp .:base C
hello interface 1
Шайкеш каталогдо m() методун абстракттуу деп жарыялаган I2 интерфейсинин versionсы, ошондой эле техникалык себептерден улам I1.javaнын өзгөртүлбөгөн көчүрмөсү бар.
~/github/test$ cat compatible/I2.java

public interface I2 {
  void m();
}
Мындай топтом C классын компиляциялоо үчүн колдонулbyte:
~/github/test$ javac -cp .:compatible C.java
C.java:1: error: C is not abstract and does not override abstract method m() in I2
public class C implements I1, I2 {
       ^
1 error
Ката кабары абдан так. Бирок, бизде мурунку компиляциядан C.class бар жана эгер интерфейстерди туура келген каталогго компиляция кылсак, классты иштетүү үчүн дагы эле колдонула турган эки интерфейсибиз болот:
~/github/test$ javac compatible/I*.java
~/github/test$ java -cp .:compatible C
hello interface 1
Үчүнчү каталог - wrong- I2 versionсын камтыйт, ал ошондой эле ыкманы жарыялайт m():
~/github/test$ cat wrong/I2.java
public interface I2 {
  default void m(){
    System.out.println("hello interface 2");
  }
}
Сиз компиляция жөнүндө тынчсыздануунун деле кереги жок. Метод эки жолу жарыяланганына карабастан, класс m() ыкмасы чакырылганга чейин колдонула берет жана иштей берет. Бул үчүн бизге буйрук сабынын аргументи керек:
~/github/test$ javac wrong/*.java
~/github/test$ java -cp .:wrong C
Exception in thread "main" java.lang.IncompatibleClassChangeError: Conflicting default methods: I1.m I2.m
    at C.m(C.java)
    at C.main(C.java:5)
~/github/test$ java -cp .:wrong C x
~/github/test$

Корутунду

Китепканаңызды Java 8ге өткөргөндө жана интерфейстериңизди демейки ыкмаларды камтууга өзгөрткөнүңүздө, сизде эч кандай көйгөй болбойт. Жок дегенде, Java 8 китепканасынын иштеп чыгуучулары функционалдык мүмкүнчүлүктөрдү кошуп, ушуну күтүшөт. Китепканаңызды колдонгон тиркемелер аны дагы деле демейки ыкмалар жок Java 7 үчүн колдонуп жатышат. Эгерде бир нече китепкана чогуу пайдаланылса, чыр-чатактын чыгышы мүмкүн. Андан кантип сактануу керек? Китепканаңыздын API'син мурункудай кылып түзүңүз. Демейки ыкмалардын мүмкүнчүлүктөрүнө таянуу менен көңүл бурбаңыз. Алар акыркы чара болуп саналат. Башка интерфейстер менен кагылышпоо үчүн аттарды кылдат тандаңыз. Келгиле, бул функцияны колдонуу менен Java үчүн өнүгүү кандайча өнүгө турганын карап көрөлү.
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION