Создайте анонимный внутренний класс и вызовите его методы

Я искал это, но, к сожалению, не нашел совпадений, у меня есть этот local anonymous inner class внутри такого метода: -

new Object(){
    public void open(){
        // do some stuff
    }
    public void dis(){
        // do some stuff
    }
};

с 2 methods внутри него (open,dis) и я знаю, что если я хочу использовать любой из них, просто сделайте

new Object(){
    public void open(){
        // do some stuff
    }
    public void dis(){
        // do some stuff
    }
}.open()

Теперь мой вопрос: Что делать, если я хочу вызвать два метода одновременно. Как я могу это сделать?


person Scorpion    schedule 04.03.2014    source источник
comment
Один из способов может заключаться в том, чтобы open возвращал this и связывал вызовы.   -  person njzk2    schedule 05.03.2014
comment
@njzk2 Я думал об этом. Но в этом случае какой тип должен возвращать open?   -  person Andrei Nicusan    schedule 05.03.2014
comment
Это имеет сильный запах кода. Если вам нужно вызвать оба метода, единственный способ сделать это - вернуть this и цепочку, но это захватывает механизм возврата и извращает любой естественный тип возврата для методов, не являющихся сеттерами. Если вам нужно вызвать оба метода, вам нужен настоящий класс.   -  person Jim Garrison    schedule 05.03.2014
comment
@Scorpion В учебниках по Java есть хороший пример docs.oracle.com /javase/tutorial/java/javaOO/   -  person Brian    schedule 05.03.2014
comment
Как насчет вызова dis() внутри open()? Разве это не поможет?   -  person Evdzhan Mustafa    schedule 05.03.2014
comment
Вы имеете в виду действительно в то же время или в том же экземпляре?   -  person robermann    schedule 05.03.2014


Ответы (3)


Вы можете создать такой интерфейс:

interface MyAnonymous {
   MyAnonymous open();
   MyAnonymous dis();  //or even void here
}

new MyAnonymous(){
    public MyAnonymous open(){
        // do some stuff
        return this;
    }
    public MyAnonymous dis(){
        // do some stuff
        return this;
    }
}.open().dis();

ИЗМЕНИТЬ ----

Как указывает @Jeff, интерфейс нужен только в том случае, если ссылка назначена. Действительно, следующее решение (вызванное @JamesB) абсолютно верно:

new MyObject(){
        public MyObject open(){
            // do some stuff
            return this;
        }
        public MyObject dis(){
            // do some stuff
            return this;
        }
    }.open().dis();

но это не будет компилироваться:

MyObject myObject = new MyObject(){
            public MyObject open(){
                // do some stuff
                return this;
            }
            public MyObject dis(){
                // do some stuff
                return this;
            }
        };
myObject.open().dis();  //not compiling since anonymous class creates a subclass of the class
person Mik378    schedule 04.03.2014
comment
@Jim Спасибо за немедленное редактирование;) Я пропустил самое важное;) - person Mik378; 05.03.2014
comment
Честно говоря, вам даже не нужен interface. А если у вас есть interface, то вообще не нужно связывать вызовы методов или вызывать их сразу после создания экземпляра объекта благодаря полиморфизму. Вам не нужно, чтобы методы возвращали сами себя. - person asteri; 05.03.2014
comment
@Jeff Мне строго не нужен интерфейс, но OP не предоставляет полного контекста, подтверждающего, что я могу его обойти. Кстати, не согласен со вторым пунктом: цепочка не имеет ничего общего с концепцией polymorphism, это просто способ иметь краткий код, полезный в некоторых случаях: en.wikipedia.org/wiki/Fluent_interface. - person Mik378; 05.03.2014
comment
Я никогда не утверждал, что цепочка связана с полиморфизмом. Я утверждаю, что благодаря полиморфизму нет причин иметь цепочку методов. Вы можете просто объявить переменную MyAnonymous object = new MyAnonymous() { /* method implementations here */ };, а затем вызвать object.open(); и object.dis(); по отдельности. - person asteri; 05.03.2014
comment
@Jeff Джефф, да, но Fluent Interface позволит преобразовать эти две строки вызовов в одну. Полезно, например, для шаблона Builder Джошуа Блоха. Объяснение здесь: stackoverflow.com/a/4342728/985949 - person Mik378; 05.03.2014
comment
Я бы настоятельно рекомендовал использовать аннотацию @Override, чтобы четко указать, что вы реализуете методы из интерфейса - person njzk2; 05.03.2014

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

interface MyAnonymous {
   void open();
   void dis();
}

MyAnonymous anon = new MyAnonymous () {
    public void open(){
        // do some stuff
    }
    public void dis(){
        // do some stuff
    }
};

anon.open();
anon.dis();
person robermann    schedule 04.03.2014
comment
Все комментарии ниже объяснили, почему интерфейс не нужен, ха-ха ;) - person Mik378; 05.03.2014
comment
конечно, дело не в этом; дело в том, что есть ссылка на родителя - person robermann; 05.03.2014
comment
Да, но ОП никогда не упоминает о чистой необходимости ссылки на родителя. - person Mik378; 05.03.2014
comment
true, только если ваша цель просто вызвать методы объекта - person robermann; 05.03.2014
comment
смысл этого решения в том, что open и dis не должны ничего возвращать - person robermann; 05.03.2014
comment
Да, это соответствует принципу CQS, поскольку open и dis определенно не будут идемпотентными. - person Mik378; 05.03.2014
comment
Если первоначальный публичный контракт заключался в том, что они были недействительными, почему вы должны были изменить его только для детали реализации, которая имеет значение только для программиста? Это плохой драйвер для изменения кода :) - person robermann; 05.03.2014
comment
Согласен, но мы не можем делать предположения о коде, который мы не видим, поэтому все возможно, и, таким образом, быть ближе к OP - это хороший способ. - person Mik378; 05.03.2014
comment
что значит ближе к ОП? - person robermann; 05.03.2014
comment
Написано жирным шрифтом: Что делать, если я хочу вызвать два метода одновременно =› смысл в одной строке - person Mik378; 05.03.2014

person    schedule
comment
MyObject не может быть преобразован в тип. Это не полный ответ. - person exception1; 05.03.2014
comment
@exception1 У вас действительно должен быть где-то класс с именем MyObject. Он бы скомпилировался для вас, если бы в примере использовалось только Object. - person asteri; 05.03.2014
comment
Ваш ответ предполагает, что MyObject существует и уже определяет (выше) эти методы. - person Mik378; 05.03.2014
comment
@Mik378 Mik378 Вы ошибаетесь, что MyObject уже должен определять эти методы. В этом весь смысл анонимного класса. Вы думаете о переопределении, что является другим вопросом/пунктом. - person asteri; 05.03.2014
comment
@Jeff Анонимное ДОБАВЛЕНИЕ некоторых методов (без полиморфизма), подклассов на самом деле соответствующего класса. Таким образом, MyObject не будет знать об этих методах. Объяснение здесь: beingjavaguys.com/2013/10 /what-is-anonymous-class-in-java.html (часть создания анонимного внутреннего класса с использованием ссылочной переменной класса). Если бы я наоборот переопределял, это скомпилировалось бы;) - person Mik378; 05.03.2014
comment
@Mik378 Mik378 Именно это и делает ОП в своем вопросе. MyObject не знает ни open(), ни dis(), как и Object. Реализация в вашем вопросе также создает анонимный подкласс MyAnonymous, и в обоих случаях отношение is-a между анонимным подклассом и родительским классом идентично. Я не уверен, в чем, по вашему мнению, заключается существенная разница между вашими двумя решениями, тем более что вы цепляете сразу после создания экземпляра объекта, как это делает Джеймс, и не используете преимущества полиморфизма. Это правильный ответ на вопрос. +1 - person asteri; 05.03.2014
comment
@Jeff Джефф Действительно, Джефф, ты совершенно прав;) Я слишком быстро прочитал ответ! Это было бы применимо, только вызовы методов были не на той же строке, что и создание. - person Mik378; 05.03.2014
comment
@Jeff Обновил мой ответ. - person Mik378; 05.03.2014
comment
@ Mik378 Я понял. Все хорошо, я тоже +1 поставила вам. Ха-ха. Оба правы. - person asteri; 05.03.2014
comment
@Jeff Будучи перфекционистом по натуре, я предпочитаю ваш, так как он более близок к конкретному случаю OP :) - person Mik378; 05.03.2014