Используя “это” с методами (в Java)

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

В этом контексте register_function не делает ничего полезного. Возвращает оболочку, которая вызывает неизмененный оригинал. Основываясь на имени, вы, вероятно, захотите записать функцию в каком-то реестре, например в словаре:

function_registry = {}

def register_command(func):
    function_registry[func.__name__] = func
    return func

Помните, что вещи, которые декоратор не должен затрагивать функцию напрямую (или совсем). И нет ничего плохого в простом возврате функции ввода.

Теперь давайте посмотрим на использование реестра, который мы только что создали. Ваш текущий execute_command ничего не выполняет. Он создает и возвращает вызываемый объект, который будет вызывать декорированную функцию, если вы будете вызывать ее без аргументов. execute_command на самом деле не вызывает результат.

Возможно, вы захотите, чтобы функция с именем, например execute_command, искала команду по имени и запускала ее:

def execute_command(name, *args, **kwargs)):
     return function_registry[name](*args, **kwargs)

Так что теперь вы можете сделать что-то вроде

@register_command
def some_math_function(variable):
    return variable + 1

Это оставит функцию неизменной, но добавит запись в реестр, которая отображает имя 'some_math_function' на объект функции some_math_function.

Ваша программа становится

func_name = input('what function do you want to run? ')  # enter some_math_func
input_var = int(input("input your variable: "))
response = execute_command(func_name, input_var)
print(response())

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


Итак, здесь есть элементарная система для преобразования фиксированного числа входов в требуемые типы. Аргументы конвертируются в указанном порядке. Функция отвечает за выдачу ошибки, если вы не указали достаточно данных. Ключевые слова не поддерживаются:

function_registry = {}

def register_function(*converters):
    def decorator(func):
        def wrapper(*args):
            real_args = (c(arg) for c, arg in zip(converters, args))
            return func(*real_args)
        function_registry[func.__name__] = wrapper
        return wrapper
    return decorator

@registrer_function(int)
def some_math_func(variable):
    return variable + 1

def execute_command(name, *args):
    return function_registry[name](*args)

command = input("command me: ")  # some_math_func 1
name, *args = command.split()
result = execute_command(name, *args)
print(result)
15
задан royhowie 11 May 2015 в 03:24
поделиться

7 ответов

Три очевидных ситуации, где Вам нужен он:

  • Вызов другого конструктора в том же классе как первая часть Вашего конструктора
  • Дифференциация между локальной переменной и переменной экземпляра (ли в конструкторе или каком-либо другом методе)
  • Передача ссылки на текущий объект к другому методу

Вот пример всех трех:

public class Test
{
    int x;

    public Test(int x)
    {
        this.x = x;
    }

    public Test()
    {
        this(10);
    }

    public void foo()
    {
        Helper.doSomethingWith(this);
    }

    public void setX(int x)
    {
        this.x = x;
    }
}

я полагаю, что существуют также некоторые странные ситуации с помощью внутренних классов, где Вам нужно super.this.x, но их нужно избежать как чрезвычайно неясные, IMO :)

РЕДАКТИРОВАНИЕ: Я не могу думать ни о каких примерах, почему Вы хотели бы это для прямого this.foo() вызов метода.

РЕДАКТИРОВАНИЕ: saua внес это по вопросу неясных внутренних примеров класса:

я думаю, что неясный случай: OuterClass.this.foo() при доступе foo() из внешнего класса из кода во Внутреннем классе, который имеет foo() метод также.

36
ответ дан 1 December 2019 в 01:00
поделиться

Я использую "это" для разъяснения кода, часто как подсказка, что я называю метод экземпляра вместо того, чтобы получить доступ к методу уровня класса или полю.

, Но нет. Если разрешение неоднозначности не требуется должное определить объем коллизии именования, Вам на самом деле не нужно "это".

2
ответ дан 1 December 2019 в 01:00
поделиться

Для самого общего программирования this ключевое слово является дополнительным и обычно раньше избегало беспорядка. Однако существует несколько мест, где это необходимо.

class Foo {
    int val;

    public Foo(int val) {
         this(val, 0);  //this MUST be here to refer to another constructor
    }

    public Foo(int val, int another) {
        val = val;       //this will work, but it generally not recommended.
        this.val = val;  //both are the same, but this is more useful.
        method1();       //in a Foo instance, it will refer to this.method1()
        this.method1();  //but in a Foo2 instance, you must use this to do the same
    }

    public void method1() {}
}

class Foo2 extends Foo {
    public Foo2(int val) {
        this(val);        //this will refer to the other Foo2 constructor
    }
    public Foo2(int val, int another) {
        super(val, another);
        super.method1();   //this will refer to Foo.method1()
    }

    @Override
    public void method1() {}//overridden method
}

Это не все случаи, но некоторые более общие. Я надеюсь, что это помогает Вам лучше понять this и super ключевые слова и как/когда использовать их.

2
ответ дан 1 December 2019 в 01:00
поделиться

Единственное время это действительно требуется, - когда у Вас есть параметр к методу с тем же именем как членская переменная. Лично, я пытаюсь всегда использовать его для создания объема переменной/метода явным. Например, у Вас могли быть статический метод или метод экземпляра. При чтении кода может быть полезно знать, который является который.

0
ответ дан 1 December 2019 в 01:00
поделиться

Не ответ (поэтому не стесняются проваливать его), но я не мог вместить это в комментарий, где кто-то спрашивал.

Много людей использует "this.x" для визуальной дифференциации переменных экземпляра от локальных переменных и параметров.

, Таким образом, они сделали бы это:

private int sum;
public int storeSquare (int b) {
    int c=b*b;
    this.sum+=c; // Makes sum "pop" I guess
    return c;
}

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

Выполнение его с "этим". только 50%-й сейф. Уверенный компилятор поймает его, при попытке поместить this.x, когда x является локальной переменной, но нет ничего, что собирается мешать Вам "Забыть" отмечать переменную экземпляра с этим., и если Вы забываете отмечать всего один (или если кто-то еще работает над Вашим кодом), и Вы полагаетесь на шаблон, затем шаблон может больше нанести ущерб, чем хороший

Лично, я абсолютно уверен основы шаблона от программистов (законный) дискомфорт с тем, что в этом случае:

public void setMe(int me) {
    this.me=me;
}

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

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

public void setMe( int pMe) 
0
ответ дан 1 December 2019 в 01:00
поделиться

Единственная причина предварительно ожидать this перед вызовом метода состоит в том, чтобы указать на вызов нестатического метода. Я не могу думать ни о какой другой допустимой причине сделать это (исправьте меня, я неправ). Я не рекомендую эту конвенцию, поскольку она не добавляет много значения. Если не применяемый последовательно затем это могло бы вводить в заблуждение (поскольку этот меньше вызов метода мог бы все еще быть нестатическим методом). Как часто каждый заботится, является ли вызываемый метод статическим или нет? Кроме того, большинство IDE выделит статические методы по-другому.

я услышал о конвенциях, где this указывает на вызов метода подкласса, в то время как отсутствие this называет метод суперкласса. Но это просто глупо, как конвенция могла быть наоборот.

Редактирование : Как mmyers указывает (см. комментарий), this работы со статическими методами. С этим я не вижу абсолютно никаких оснований для предварительного ожидания с this, поскольку это не имеет никакого значения.

0
ответ дан 1 December 2019 в 01:00
поделиться

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/StringBuilder.html

Вам абсолютно нужно это, если Ваш метод должен возвратить экземпляр объекта.

public class StringBuildable {
    public StringBuildable append(String text) {
        // Code to insert the string -- previously this.internalAppend(text);
        return this;
    }
}

Это позволяет Вам цепочечным методам вместе следующим способом:

String string = new StringBuildable()
    .append("hello")
    .append(' ')
    .append.("World")
    .toString()
;
0
ответ дан 1 December 2019 в 01:00
поделиться
Другие вопросы по тегам:

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