您需要多长时间才能听到回声,那么您就知道了往返的总时间。
Java:A初学者指南,第六版-赫伯特·希尔德(Herbert Schildt)·麦格劳-希尔教育(McGraw-Hill Education)(第2章) -说话。我已将逻辑尽可能地分为一类(以我目前的技能水平)。
SoundSpeed.java
public class SoundSpeed {
private final double SOUND_TRAVEL_SPEED = 1100;
public double timeInSeconds;
public boolean isEcho;
private int distanceDivisor;
double getResult() {
if(isEcho) {
distanceDivisor = 2;
} else {
distanceDivisor = 1;
}
return (timeInSeconds * SOUND_TRAVEL_SPEED) / distanceDivisor;
}
}
SoundSpeedCalc.java
class SoundSpeedCalc {
public static void main(String args[]) {
SoundSpeed soundSpeed = new SoundSpeed();
soundSpeed.timeInSeconds = 35.079;
soundSpeed.isEcho = true;
String verb;
if(soundSpeed.isEcho) {
verb = "echo";
} else {
verb = "travel";
}
System.out.println("The sound took " + soundSpeed.timeInSeconds + " seconds to "
+ verb + " and thus the distance is " + soundSpeed.getResult() + " feet away.");
}
}
示例输出(使用
main
中的上述参数):声音花费了35.079秒回声,因此距离为19293.45英尺。
示例输出如果我将
soundSpeed.isEcho
设置为false
:声音耗时35.079秒传播,因此距离为38586.9英尺。
#1 楼
您只想简单地public static double distanceBySounding(double seconds, boolean isEcho) {
return (isEcho ? 0.5 : 1.0) * seconds * 1100 /* ft. per second */;
}
问题是,该函数应如何以面向对象的方式表达?可以肯定地说,这个……
SoundSpeed soundSpeed = new SoundSpeed();
soundSpeed.timeInSeconds = 35.079;
soundSpeed.isEcho = true;
System.out.println(soundSpeed.getResult());
…是一个令人讨厌的界面。像这样处理公共实例变量不仅麻烦,而且是不明智的做法(对不起)。给定以上两个选项之间的选择,相对于扭曲的对象,我更喜欢简单的函数。很好。 Java允许您编写不完全符合OOP的代码。
如果要面向对象的设计该怎么办?面向对象设计的关键是要对对象建模。这意味着您必须找到合理的对象进行建模-越真实越好。什么是SoundSpeedCalc?我不知道;你买不到。但是您可以确定购买声纳!用配置参数(声音介质及其主动/被动模式)实例化
Sonar
是有意义的,然后您可以通过调用.distance()
来开始“命名”它。public class Sonar {
public enum Medium {
AIR(1100);
private final double ftPerSec;
Medium(double ftPerSec) {
this.ftPerSec = ftPerSec;
}
}
private final Medium medium;
private final boolean isEcho;
public Sonar(Medium medium, boolean isEcho) {
this.medium = medium;
this.isEcho = isEcho;
}
public double distance(double seconds) {
return medium.ftPerSec * seconds / (isEcho ? 2 : 1);
}
}
这里是如何有效使用它的方法:另外,我使用了条件表达式-这是根据布尔开关分配两个值之一的理想方法。
#2 楼
其他名称的结果是否闻起来有甜味?timeInSeconds
的常规名称是seconds
SOUND_TRAVEL_SPEED
可能会受益于说明单位和其他假设的注释: SPEED_OF_SOUND
可以使用更具描述性的名称。 要实例化还是不实例化,这就是问题。
SOUND_TRAVEL_SPEED
可能不需要实例化。可以将getResult
保持不变,并使用feet
函数进行计算,这可能很好:/* approximate, feet/second at sea level */
评论
\ $ \ begingroup \ $
我不同意你的第一行。切勿以其单位调用变量或参数。时间是可以接受的,elapsedTime,travelTime或该概念的其他变化也可以接受。例外:如果要进行单位转换,则单位将是可接受的参数名称。
\ $ \ endgroup \ $
–克里斯·库德莫(Chris Cudmore)
2015年2月23日在17:42
\ $ \ begingroup \ $
@ChrisCudmore我以为我们正在进行单位转换。
\ $ \ endgroup \ $
–韦恩·康拉德
15年2月23日在18:56
\ $ \ begingroup \ $
@ChrisCudmore,为什么不呢?我有多个引用,在变量名称中包括度量单位是一个好习惯。
\ $ \ endgroup \ $
– Vorac
2015年2月24日12:41
\ $ \ begingroup \ $
让我们看一下函数调用:feet(double seconds,boolean isEcho)它返回什么?脚?不,它返回一个距离。它需要什么参数?需要一些时间。您可以使它们更明确,例如distanceTravelled和sonarPingTime。单位应该是API文档的一部分,或者更可靠地作为参数(例如Units.SECONDS)
\ $ \ endgroup \ $
–克里斯·库德莫(Chris Cudmore)
15年2月24日在13:30
\ $ \ begingroup \ $
@ChrisCudmore如果变量的含义在上下文中很清楚,并且更改它们将需要添加注释以传达相同的意图,则该规则将损害代码,而无济于事。但是,我确实同意,通过使用单位库或使用单位参数来明确指定单位通常会更好。
\ $ \ endgroup \ $
–韦恩·康拉德
15年2月24日在16:26
#3 楼
SOUND_TRAVEL_SPEED
也应该是static
:private static final double SOUND_TRAVEL_SPEED = 1100;
这是因为它不属于特定的类实例。 >
其他数据成员仍然应该是
private
:private double timeInSeconds;
private boolean isEcho;
这通常适用于所有类。
>可以通过三元语句简化
getResult()
中的计算: /> 评论
\ $ \ begingroup \ $
我尝试将这两个设置为私有,但是在运行SoundSpeedCalc时出现编译器错误... SoundSpeed.timeInSeconds字段不可见,等等。是否还需要更改?
\ $ \ endgroup \ $
– ran
2015年2月23日在1:30
\ $ \ begingroup \ $
@Phrancis:这是因为您在声明实例后设置其值,因此不允许修改该私有字段。您应该改为使用该值构造soundSpeed。
\ $ \ endgroup \ $
– Jamal♦
2015年2月23日在1:32
\ $ \ begingroup \ $
“ SOUND_TRAVEL_SPEED也应该是静态的:”这将排除在水下将此类用于SONAR。
\ $ \ endgroup \ $
–阿伦
2015年2月23日下午6:52
#4 楼
只是一件事:没有以
is
开头的布尔字段。就像这样:public boolean isEcho;
(200_success和其他正确的说法,它不应该是
public
)吸气剂是它们应该以is
开头,后跟它们是吸气剂的变量的名称。假设这个变量有一个吸气剂:public boolean isIsEcho() {
return this.isEcho;
}
现在听起来很奇怪!
变量和变量的正确命名约定其吸气方法是:
private boolean echo;
public boolean isEcho() {
return this.echo;
}
评论
\ $ \ begingroup \ $
OP的“面向对象”方法使我想起了我的AP计算机科学课。不正确或不实际,但足以教授对象的基础知识
\ $ \ endgroup \ $
–科尔·约翰逊(Cole Johnson)
2015年2月23日在14:18
\ $ \ begingroup \ $
@ColeJohnson:的确,这些示例的问题通常是,通过删除任何可能掩盖所涉及的OOP技术的实质性内容,您最终会遇到一个琐碎的问题,很难证明抛出任何类型的错误是合理的从根本上讲,这是技术上的问题,并且所得到的代码是荒谬的;-)更现实的是,可以在测试工具中看到这些抽象的价值,因为这表明了其所有主要用途。如果您的目标只是将输入乘以1100的函数,那么您已经迷失了方向,我们需要有趣的要求来编写有趣的代码!
\ $ \ endgroup \ $
–史蒂夫·杰索普(Steve Jessop)
2015年2月23日在16:30
\ $ \ begingroup \ $
+1喜欢为真实物体建模的要点。我们常常忘记这一点。为了可扩展性,与枚举相比,我更喜欢MEDIUM的接口和最终实现。
\ $ \ endgroup \ $
–psaxton
2015年2月25日于4:00