Java: Создание подкласса возражает от родительского объекта

Пример GUI:

Предположим, что у меня есть GUI:

import tkinter as tk

root = tk.Tk()

btn = tk.Button(root, text="Press")
btn.pack()

root.mainloop()

Что происходит при нажатии кнопки

См., когда btn нажата, вызывает свою собственную функцию , которая очень похожа на button_press_handle в следующем примере:

def button_press_handle(callback=None):
    if callback:
        callback() # Where exactly the method assigned to btn['command'] is being callled

с:

button_press_handle(btn['command'])

Вы может просто предположить, что параметр command должен быть установлен как ссылка на метод, который мы хотим назвать, аналогичный callback в button_press_handle.


Вызов метода ( Callback ) Когда кнопка нажата

Без аргументов

Итак, если я хотел print что-то при нажатии кнопки I необходимо установить:

btn['command'] = print # default to print is new line

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

W ith Аргумент (ы)

Теперь Если бы я хотел также передать аргументы методу, который я хочу называть при нажатии кнопки, я мог бы использовать анонимные функции, которые могут быть созданы с помощью оператора lambda , в этом случае для встроенного метода print, например:

btn['command'] = lambda arg1="Hello", arg2=" ", arg3="World!" : print(arg1 + arg2 + arg3)

Вызов Несколько методов при нажатии кнопки

Без Аргументы

Вы также можете добиться этого с помощью оператора lambda, но он считается плохим и поэтому я не буду включать его здесь. Хорошей практикой является определение отдельного метода multiple_methods, который вызывает нужные методы, а затем устанавливает его как ответ на нажатие кнопки:

def multiple_methods():
    print("Vicariously") # the first inner callback
    print("I") # another inner callback

С Аргумент (s)

Чтобы передать аргумент (ы) методу, который вызывает другие методы, снова используйте инструкцию lambda, но сначала:

def multiple_methods(*args, **kwargs):
    print(args[0]) # the first inner callback
    print(kwargs['opt1']) # another inner callback

, а затем установите :

btn['command'] = lambda arg="live", kw="as the" : a_new_method(arg, opt1=kw)

Возвращаемый объект (ы) из обратного вызова

Также обратите внимание, что callback не может реально return, потому что он только вызывается внутри button_press_handle ] с callback() в отличие от return callback(). Это делает return, но не вне этой функции. Таким образом, вам лучше изменить объект (ы), которые доступны в текущей области.


Полный пример с global Модификация объекта (ов)

Ниже приведен вызов метода, который меняет текст btn при каждом нажатии кнопки:

import tkinter as tk

i = 0
def text_mod():
    global i, btn           # btn can be omitted but not sure if should be
    txt = ("Vicariously", "I", "live", "as", "the", "whole", "world", "dies")
    btn['text'] = txt[i]    # the global object that is modified
    i = (i + 1) % len(txt)  # another global object that gets modified

root = tk.Tk()

btn = tk.Button(root, text="My Button")
btn['command'] = text_mod

btn.pack(fill='both', expand=True)

root.mainloop()

Зеркало

36
задан 12 March 2009 в 11:13
поделиться

5 ответов

Да, просто добавьте конструктора для Грузоперевозок. Вы, вероятно, захотите добавить конструктора к Автомобилю также, хотя не обязательно общедоступный:

public class Car {
    protected Car(Car orig) {
    ...
}

public class Truck extends Car {
    public Truck(Car orig) {
        super(orig);
    }
    ...
}

, Как правило, обычно лучше сделать классы любым листом (и Вы могли бы хотеть отметить окончательных), или краткий обзор.

выглядит, как будто Вы хотите Car объект и затем имеете тот же экземпляр, превращаются Truck. Лучший способ сделать это состоит в том, чтобы делегировать поведение к другому объекту в Car (Vehicle). Так:

public final class Vehicle {
    private VehicleBehaviour behaviour = VehicleBehaviour.CAR;

    public void becomeTruck() {
        this.behaviour =  VehicleBehaviour.TRUCK;
    } 
    ...
}

, Если Вы реализуете Cloneable тогда, можно "автоматически" скопировать объект в экземпляр того же класса. Однако существует много проблем с этим, включая необходимость скопировать каждое поле изменяемых объектов, которое подвержено ошибкам и запрещает использование финала.

33
ответ дан Tom Hawtin - tackline 10 October 2019 в 10:50
поделиться

Вы могли использовать API Reflection, чтобы циклично выполниться через каждое из полей Car и присвоить значение эквивалентным полям Truck. Это может быть сделано в грузовике. Далее это - единственный способ получить доступ к частным полям Автомобиля - по крайней мере, в автоматическом смысле, если это менеджер безопасности не существует и доступ ограничения к частному полю.

0
ответ дан Martin OConnor 10 October 2019 в 10:50
поделиться

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

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

4
ответ дан Jon Skeet 10 October 2019 в 10:50
поделиться

я должен был бы записать моему собственному конструктору копии? Это должно было бы быть обновлено каждый раз, Автомобиль получает новое поле...

По существу, да - Вы не можете только преобразовать объект в Java.

, К счастью, Вы не должны писать весь код сами - изучают свободное-городское-население-beanutils , конкретно методы как cloneBean. Это имеет добавленное преимущество, что Вы не должны обновлять его каждый раз, когда это получает новое поле!

2
ответ дан 10 October 2019 в 10:50
поделиться

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

0
ответ дан tvanfosson 10 October 2019 в 10:50
поделиться
Другие вопросы по тегам:

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