Java 如何有效地将方法划分为子方法?
因此,这个线程的基本结论是,我希望一些私有方法只表示另一个方法中的代码块。我知道范围界定在Java中是如何工作的,但有时我希望事情能以不同的方式工作: 假设在我的类中有一个方法doLotsOfStuff(),它可以做多种事情。很自然地,我们会将这些东西分成几个类型为VOID的方法doThis()和doThat()。您会遇到此类问题: 1) 在doThis()和doThat()中的dolotsoftuff()中定义的任何数据上,如果不首先传递所需的所有必要参数,我将无法再操作这些数据,这不会使它们无效!例如doThis(int dolotsofstfulsint)这意味着如果我想要一个调用链,那么必须在一行参数中传递相同的变量。。这就导致了: 2) 设置为private的doThis()和doThat()对于同一类中的所有其他方法仍然可见,尽管我只想将它们用于doLotsOfStuff()。拥有一长串只打算一次使用的子方法将使整个类变得混乱 以下是我希望存在的东西: a、 b、c、d是同一类中的私有方法。->表示对方法的调用 a()->b()->c() c()可以自由使用a()或b()中的变量,而无需在整个链中传递参数 d()-/->c() d()不能调用c(),因为c()只对a()及其任何后续调用方“本地” 举个简单的例子:Java 如何有效地将方法划分为子方法?,java,Java,因此,这个线程的基本结论是,我希望一些私有方法只表示另一个方法中的代码块。我知道范围界定在Java中是如何工作的,但有时我希望事情能以不同的方式工作: 假设在我的类中有一个方法doLotsOfStuff(),它可以做多种事情。很自然地,我们会将这些东西分成几个类型为VOID的方法doThis()和doThat()。您会遇到此类问题: 1) 在doThis()和doThat()中的dolotsoftuff()中定义的任何数据上,如果不首先传递所需的所有必要参数,我将无法再操作这些数据,这不会使它们
private void someMethod()
{
char a = 'a';
printA();
}
private void printA() {
System.out.println(a); //a cannot resolve, but I don't want to pass it as an argument from someMethod()!
}
有没有一种方法可以实现这一点,而不必通过一个参数?某种形式的声明
“私有void printA()依赖于someMethod”
这不是一个很好的功能吗?若否,原因为何?您将如何做到这一点?您的建议与大多数称为范围的编程语言中的范例背道而驰 该方法存在的原因是封装了较大程序的一部分功能,使其易于理解和重用 分解一个大方法以使其易于理解是很好的(即使只调用一次该方法),但是如果您发现自己需要访问原始大方法中的许多变量,我会质疑是否真的有必要分解它 如果语言允许方法访问其他方法中的变量,那么跟踪程序中发生的事情将成为一场噩梦 我在网上找到了这个有趣的类比,我认为它在这里很适用 想象一下,你有一个非常好的工具集合非常好。 现在想象一下,你决定把你的工具借给任何一个 问。除非你有特别的邻居,否则你可能会找到它 最终需要修改此策略,因为其中一些工具 将以破碎而告终,而其他人将永远消失而无影无踪
如果一个方法非常复杂,即使将其拆分为子方法和传递参数也会使类变得混乱,那么这可能是一个好迹象,表明您需要委托给另一个有状态类 例如:
private void someMethod() {
ComplexPrinter printer = ComplexPrinter('a');
printer.foo();
printer.bar();
printer.baz();
}
或者至少,为了避免向每个方法传递太多参数,将它们存储在单个上下文对象中:
private void someMethod() {
PrintContext context = PrintContext('a', 'b', 'c', 'd', 'e');
foo(context);
bar(context);
baz(context);
}
您正在寻找的内容称为范围界定:
闭包
在Java
中不受本机支持,老实说,模仿起来也不是很优雅。这种能力在大多数动态语言中都是固有的,比如Groovy
或JavaScript
A捕获其定义范围内的变量
您可以在内部类中引用它们,并用内部类模拟闭包中的数据隐藏行为
输出
这会对公共界面隐藏内部详细信息。
这将完成您要查找的数据/方法隐藏。这是一个
方法对象模式实现排序,可能会绊倒新程序员,因为它在Java中不经常使用。这种内部类的使用在Python、JavaScript和Ruby等动态语言中非常普遍
这有助于在支持代码折叠的良好IDE中分离代码。如果您将IDE设置为折叠所有内部类,则会减少源代码
吵闹
多行代码并不总是坏事,如果你能更容易地使用Intellij IDEA这样的工具自动重构一些东西,那么多行代码就更好了,因为它可以自动维护
多写几行代码来缩小范围几乎总是更好的。范围越窄,可能产生的副作用就越少,维护和调试就越容易,因为由于范围狭窄,代码的影响和代码的影响最小,并且非常明显
这个习惯用法在Java中主要用于Iterator
和FluentBuilder
模式实现,以隐藏实现的细节。这里有一个例子
如果您有多个实现,可选择使用接口:
这是同样的工作方式,但是如果您需要同一接口的不同行为
,则可以创建多个实现
public static class Example
{
interface ClosureLikeThing
{
public ClosureLikeThing doThis();
public ClosureLikeThing doThat();
}
public void doSomething(final int a, final int b)
{
new ClosureLikeThing()
{
@Override
public ClosureLikeThing doThis()
{
System.out.println("a = " + a);
return this;
}
@Override
public ClosureLikeThing doThat()
{
System.out.println("b = " + b);
return this;
}
}.doThis().doThat();
}
}
基于:
您可以创建一个“方法对象”,向其构造函数传递所有参数,然后可以在其任何方法中自由使用这些参数:
假设你有:
public class SomeClass
{
private void someMethod()
{
char a = 'a';
char b = 'b';
char c = 'c';
System.out.println(a);
/* Lots of code here */
System.out.println(b);
/* More lots of more code here */
System.out.println(c);
}
}
你可以把它变成:
public class SomeClass
{
private void someMethod()
{
LongMethod lm = new LongMethod('a', 'b', 'c');
lm.printA();
lm.printB();
lm.printC();
}
private static class LongMethod
{
private char a;
private char b;
private char c;
public LongMethod(char a, char b, char c)
{
this.a = a;
this.b = b;
this.c = c;
}
public void printA()
{
/* A third of a lot of code here */
System.out.println(a);
}
public void printB()
{
/* A third of a lot of code here */
System.out.println(b);
}
public void printC()
{
/* A third of a lot of code here */
System.out.println(c);
}
}
}
也许a适合您的需要?我不是JVM方面的专家,但我认为在执行时,printA(inta)
vsprintA()
使用成员变量的效率几乎没有差别。当谈到可读性和减少杂乱时,考虑使用一个内部类。我想您已经知道了这一点,但是如果您想避免将变量“a”传递给printA(),您应该
public class SomeClass
{
private void someMethod()
{
char a = 'a';
char b = 'b';
char c = 'c';
System.out.println(a);
/* Lots of code here */
System.out.println(b);
/* More lots of more code here */
System.out.println(c);
}
}
public class SomeClass
{
private void someMethod()
{
LongMethod lm = new LongMethod('a', 'b', 'c');
lm.printA();
lm.printB();
lm.printC();
}
private static class LongMethod
{
private char a;
private char b;
private char c;
public LongMethod(char a, char b, char c)
{
this.a = a;
this.b = b;
this.c = c;
}
public void printA()
{
/* A third of a lot of code here */
System.out.println(a);
}
public void printB()
{
/* A third of a lot of code here */
System.out.println(b);
}
public void printC()
{
/* A third of a lot of code here */
System.out.println(c);
}
}
}