Чем отличаются поставщики.invoke () и поставщик () в лямбда в Котлине? [Дубликат]

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

import java.util.Comparator;
import java.util.PriorityQueue;

public class Main {
    public static void main(String... args) {
        PriorityQueue<Flight> flights = new PriorityQueue<Flight>(5, new SortQueueViaPriority());
        flights.add(new Flight("0001", 9));
        flights.add(new Flight("0002", 7));
        flights.add(new Flight("0003", 1));
        flights.add(new Flight("0004", 2));
        flights.add(new Flight("0005", 1));

        while (!flights.isEmpty())
            System.out.println(flights.remove());
    }
}

class SortQueueViaPriority implements Comparator<Flight> {
    @Override
    public int compare(Flight f1, Flight f2) {
        return Integer.compare(f2.getPriority(), f1.getPriority());
    }
}

class Flight {
    private final String name;
    private final int priority;

    Flight(String name, int priority) {
        this.name = name;
        this.priority = priority;
    }

    public int getPriority() {
        return priority;
    }

    @Override
    public String toString() {
        return "Flight{" +
                "name='" + name + '\'' +
                ", priority=" + priority +
                '}';
    }
}

печатает

Flight{name='0001', priority=9}
Flight{name='0002', priority=7}
Flight{name='0004', priority=2}
Flight{name='0003', priority=1}
Flight{name='0005', priority=1}

Примечание: PriorityQueue сортирует записи таким образом, что только первый элемент будет маленький. Если вы перейдете по очереди, вы увидите все элементы, но они могут быть или не быть в порядке.

1
задан Avijit Karmakar 1 August 2017 в 03:29
поделиться

2 ответа

Да, вы можете перегрузить invoke. Вот пример:

class Greeter(val greeting: String) {
    operator fun invoke(target: String) = println("$greeting $target!")
}

val hello = Greeter("Hello")
hello("world")  // Prints "Hello world!"

В дополнение к тому, что сказал @ holi-java, переопределение invoke полезно для любого класса, где есть четкое действие, необязательно взятие параметров. Это также отлично, как функция расширения классов библиотеки Java с таким методом.

Например, скажем, что у вас есть следующий класс Java

public class ThingParser {
    public Thing parse(File file) {
        // Parse the file
    }
}

. В Kotlin вы можете определите расширение ThingParser следующим образом:

operator fun ThingParser.invoke(file: File) = parse(file)

И используйте его так:

val parser = ThingParser()
val file = File("path/to/file")
val thing = parser(file)  // Calls Parser.invoke extension function
5
ответ дан Ruckus T-Boom 16 August 2018 в 01:53
поделиться
  • 1
    Не могли бы вы более подробно объяснить второй пример. – Avijit Karmakar 18 July 2017 в 19:07
  • 2
    Конечно, если вы можете сказать мне, что вы хотели бы разработать. Есть ли какая-то часть, в частности, это не имеет смысла? – Ruckus T-Boom 18 July 2017 в 19:10
  • 3
    Просто объясните вторую программу более тщательно. – Avijit Karmakar 18 July 2017 в 19:13
  • 4
    Я очистил его, чтобы показать только важные бит. ThingParser просто анализирует файл и преобразует его содержимое в Thing. То, что это или как это работает, не имеет значения, просто что у него есть функция parse(File), которая является явным основным действием класса. – Ruckus T-Boom 18 July 2017 в 19:41
  • 5
    Parser.invoke (файл: файл) или ThingParser.invoke (файл: файл) – Avijit Karmakar 18 July 2017 в 19:44

Наиболее удобный способ использования invoke использует его как Factory Method , например:

//          v--- call the invoke(String) operator 
val data1 = Data("1")

//            v--- call the invoke() operator 
val default = Data()

//          v-- call the constructor
val data2 = Data(2)

Это происходит потому, что объект-компаньон является специальным объектом в Котлине. В самом деле, код Data("1") выше переводится в код, как показано ниже:

val factory:Data.Companion = Data

//                       v-- the invoke operator is used here
val data1:Data = factory.invoke("1")

class Data(val value: Int) {

    companion object {
        const val DEFAULT =-1
        //           v--- factory method
        operator fun invoke(value: String): Data = Data(value.toInt())

        //           v--- overloading invoke operator
        operator fun invoke(): Data = Data(DEFAULT)
    }
}
4
ответ дан holi-java 16 August 2018 в 01:53
поделиться
  • 1
    @AvijitKarmakar Совсем нет. не за что, :) – holi-java 18 July 2017 в 20:12
  • 2
    почему бы не использовать значение по умолчанию для параметра? – Antek 31 July 2017 в 08:40
  • 3
    @Antek эй, это всего лишь пример для введения заводского метода. если вы внесете Data в интерфейс, вы поймете, почему? – holi-java 31 July 2017 в 11:21
  • 4
    @ holi-java hmm, на самом деле - вы можете использовать значения по умолчанию для интерфейсов. Можете ли вы объяснить дальше? – Antek 8 August 2017 в 15:46
Другие вопросы по тегам:

Похожие вопросы: