Есть отличная удаленная работа для php+codeception+jenkins+allure+docker спецов. 100% remote! Присоединиться к проекту

Последовательный вызов методов.


(Alex) #1

В программировании на Java очень часто встречаю “Последовательный вызов методов”.

Например:

driver.findElement(By.id("")).click();
или
loginPage.getData().verifyData();
или
method.getText().trim().verify();

И вроде бы разобрался, что каждый из методов возвращает класс следующего. Но каким образом ..click(); .verifyData(); и .verify(); определяют что произошло в предыдущем методе? Спасибо

P.S. Если есть возможность объясните на простом примере


(sidelnikovmike) #2

никак :smile:


(Руслан) #3

Определяет по наличию, наверное…Тут больше похоже на true/false: если нашло что-то - идёт дальше, нет - упало


(rpwheeler) #4

А что значит “определяют что произошло в предыдущем”?
Это же последовательный вызов, а не последовательное определение.
На каждом шаге у нас есть объект и метод, который вызывается применительно к этому объекту.
Объект 1 - Метод 1
Объект 2 - Метод 2
Объект 3 - Метод 3
И это вроде как всё, что нам нужно.


(Alex) #5

Дело в том что например вот здесь есть пример:

print(getCity().getStreet().getHouse().getFlat().getRoom());

Исходя из этого можно предположить, что есть изначально некий список городов из которого берется только 1, уже на основе этого города берется определенная улица итд. Это так работает?


(Александр Таранков) #6

Это псевдокод. То есть код, который может реально не работать, а используется лишь для демонстрации какой-то идеи


(rpwheeler) #7

Предположения неверные.

Это всего лишь вызовы методов, и ничего кроме наличия таких методов, совместимости вызовов по типам объектов к которым они применяются, и того, что последний объект должен иметь метод, обеспечивающий работу print(), оно не предполагает.

Методы getЧто-то() традиционно предназначены вообще, как я читал, именно для инкапсуляции, скрытия реализации данных и кода от пользователя. Вы можете не знать (и не должны, в общем случае, знать), что внутри и как работает этот getЧто-то(), вы знаете только что и какого типа он может вам вернуть.

(поправьте меня более знающие товарищи, если прочитанное где-то ввело меня в заблуждение)


(Александр Таранков) #8

Как ты сам представляешь метод getCity() может вернуть тебе 1 город из списка? Именно тот, который нужен. Магии ведь не существует :smile:

Короче, ты сделал неверные выводы на основе недостаточности информации. Это работает не так. А как это работает, выше уже написали: предыдущий вызов в цепочке возвращает объект, метод которого вызывается следующим. Всё просто. Никакой магии


(rpwheeler) #9

Я думаю, тут нужны более подробные пояснения.
Метод getCity() не имеет параметров, то есть в нём нет никакого указания на то, что вообще существует какой-то список, тем более индексированный.

В таком стиле называются методы типа getter, назначение которых в выдаче по запросу какой-то информации об объекте.

Допустим, есть объект “Address”, у которого могут быть поля Country , City, Street, … и т.д… а может и не быть вообще полей, а быть связь с какой-то базой данных.

getCity() выдает город без уточнения где он его берёт и какие процедуры надо выполнять с тем, что берётся, до выдачи (допустим, тому, кто использует объект, не обязательно знать, что город может быть взят из базы данных и “расшифрован” ибо в базе данные хранятся в зашифрованном виде).


(Alex) #10

Но используя геттеры мы возвращаем переменную, для которой было ранее установлено значение. А для реализации “Последовательного вызова методов” нам нужно вернуть класс в котором есть следующий метод, разве нет? Я просто не пойму, в таком методе, каждый метод существует сам по себе?


(rpwheeler) #11

Но используя геттеры мы возвращаем переменную, для которой было ранее установлено значение.

Почему обязательно переменную? Класс может включать другие классы, и в возвращении методом одного класса другого класса нет ничего крамольного.

Я просто не пойму, в таком методе, каждый метод существует сам по себе?

Есть объекты и методы. Как я уже описал выше,
Объект 1 - Метод 1
Объект 2 - Метод 2
Объект 3 - Метод 3
Всё.

Указанный сложный вызов может описывать “матрёшечный” объект, в котором внутри класса Город класс Улица и метод вернутьУлицу, внутри класса Улица есть класс Дом и метод вернутьДом и т.д.
“В зайце утка, в утке яйцо, в яйце игла, а в игле смерть Кощеева”
А что пример искусственный, ну так правильно выше сказали, на то он и пример.


(Alex) #12

Спасибо. После фразы матрешка, что-то прояснилось, скорее главное сейчас попробовать это на практике.


(vmaximv) #13

Попробую внести еще немного “тумана” в данный вопрос. Помимо “матрешечного” варианта, объект может возвращать и самого себя

class A{
  public A print(){
    System.out.println("Hello!");
    return this;
  }
}
new A().print().print().print().print().print().print();

(Alex) #14

Спасибо за ответы, теперь стало понятно и уже во всю экспериментирую. =)


(rpwheeler) #15

Может-то он может :slight_smile: Но если возвращает себя, то в чём тогда смысл вызова “цепочкой” getter’ов вместо вызова всего одного из них? :smile: Как по мне, то если возвращает себя, логика такой цепочки getter’ов теряется.


(vmaximv) #16

А кто сказал, что рассматриваются только геттеры?

new Actions(driver).moveToElement(el).clickAndhold().moveByOffset(10,10).release().perform();

new MyPage().fill(data).save().verify(data).close();


(sidelnikovmike) #17

Тут кажется , что нужно понять, что следующий метод работает только с возвращаемым значением. Что реально произошло в предыдущем - следующий не знает. Да и его это мало волнует. Ему важно, чтобы у него был нужный объект с нужными ему данными(если внутри него какая-то логика зашита с этими данными)

Это как когда вы приходите в магазин за молоком. магазин(как объект) может вернуть вам молоко. Вы делаете из него коктейль и передаете дальше. Ни вам неизвестно, как магазин получил молоко, и получающему коктейль неизвестно (да и не важно) - как вы сделали коктейль. Каждому важен лишь получаемый им объект. А что произошло для получения этого объекта - остается неизвестным.


(Alex) #18

Вчера когда пробовал “матрешечный” стиль =) Наткнулся попутно в книге “Совершенный код”, что такой стиль кроет в себе и палки. Если ты вызываешь следующий метод не связанный с предыдущим. И действительно когда я посмотрел какие методы у меня доступны, оказалась полная белиберда (доступны были методы не характерные для определенной страницы). Я ведь правильно понимаю, что следующий вызов метода должен все же не нарушать логическую связь с предыдущим и чтобы у пользователя не было доступа к лишним методам?


(Sergey Korol) #19

Последовательность задаете вы сами, посему и ответственность за возвращаемый тип / логику / построение связей лежит на вас. Но в случае наследования от абстрактной пейджи, вам в любом случае IntelliSense будет выдавать список доступных методов как текущей страницы, так и родителя(-ей). Но, к примеру, IntelliJ IDEA при этом выделяет жирным шрифтом методы доступные в пределах текущего класса.


Оптимизация Framework или одинаковый функционал на некоторых страницах
(Александр Таранков) #20

Ты лучше покажи что там за матрешечный стиль. А-то “на пальцах” каждый по-своему понимает. Я так понял, что ты вложенные классы мутишь