patternjavaMajor
Calculate distance using speed of sound
Viewed 0 times
distanceusingcalculatesoundspeed
Problem
I've been working on learning Java and this was a challenge as part of a chapter on data types:
Create a program that computes how far away, in feet, a listener is
from a sound. Sound travels approximately 1,100 feet per second
through air.
You can also compute the distance to a large object, such as a rock
wall, by timing the echo. For example, if you clap your hands and time
how long it takes for you to hear the echo, then you know the total
round-trip time.
Java: A Beginner's Guide, Sixth Edition - by Herbert Schildt · McGraw-Hill Education (Chapter 2)
I'm super-new to OOP and am trying to nip bad habits in the bud, so-to-speak. I've divided the logic in one class as much as I think is possible (at my current skill level).
SoundSpeed.java
SoundSpeedCalc.java
Example output (using above parameters in
The sound took 35.079 seconds to echo and thus the distance is 19293.45 feet away.
Example output if I set
The sound took 35.079 seconds to travel and thus the distance is 38586.
Create a program that computes how far away, in feet, a listener is
from a sound. Sound travels approximately 1,100 feet per second
through air.
You can also compute the distance to a large object, such as a rock
wall, by timing the echo. For example, if you clap your hands and time
how long it takes for you to hear the echo, then you know the total
round-trip time.
Java: A Beginner's Guide, Sixth Edition - by Herbert Schildt · McGraw-Hill Education (Chapter 2)
I'm super-new to OOP and am trying to nip bad habits in the bud, so-to-speak. I've divided the logic in one class as much as I think is possible (at my current skill level).
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.");
}
}Example output (using above parameters in
main):The sound took 35.079 seconds to echo and thus the distance is 19293.45 feet away.
Example output if I set
soundSpeed.isEcho to false:The sound took 35.079 seconds to travel and thus the distance is 38586.
Solution
What you want to do is simply
The question is, how should this function be expressed in an object-oriented way? It's pretty safe to say that this…
… is an unpalatable interface. Manipulating public instance variables like that is not only cumbersome, it is an unsound practice (pardon the pun). Given a choice between the two options above, I would much prefer the simpler function to the contorted object. And that's fine. Java allows you to write code that doesn't fully conform to OOP.
What if you wanted an object-oriented design? The key to object-oriented design is that you want to model objects. That means that you have to find plausible objects to model — the more realistic, the better. What's a SoundSpeedCalc? I don't know; you can't buy one. But you can sure buy a sonar! It makes sense to instantiate a
Here's how you can use it effectively:
Note the use of
public static double distanceBySounding(double seconds, boolean isEcho) {
return (isEcho ? 0.5 : 1.0) * seconds * 1100 /* ft. per second */;
}The question is, how should this function be expressed in an object-oriented way? It's pretty safe to say that this…
SoundSpeed soundSpeed = new SoundSpeed();
soundSpeed.timeInSeconds = 35.079;
soundSpeed.isEcho = true;
System.out.println(soundSpeed.getResult());… is an unpalatable interface. Manipulating public instance variables like that is not only cumbersome, it is an unsound practice (pardon the pun). Given a choice between the two options above, I would much prefer the simpler function to the contorted object. And that's fine. Java allows you to write code that doesn't fully conform to OOP.
What if you wanted an object-oriented design? The key to object-oriented design is that you want to model objects. That means that you have to find plausible objects to model — the more realistic, the better. What's a SoundSpeedCalc? I don't know; you can't buy one. But you can sure buy a sonar! It makes sense to instantiate a
Sonar with its configuration parameters (the sound medium and its active/passive mode), then you can start "aiming" it at stuff by calling .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);
}
}Here's how you can use it effectively:
public static void main(String[] args) {
double seconds = 35.079;
boolean isEcho = true;
Sonar sonar = new Sonar(Sonar.Medium.AIR, isEcho);
String verb = isEcho ? "echo" : "travel";
System.out.printf("The sound took %s seconds to %s and thus the distance is %s feet.\n",
seconds, verb, sonar.distance(seconds));
}Note the use of
System.out.printf() as a nicer alternative to string concatenation. Also, I've used conditional expressions — it's a perfect way to assign one of two values depending on a boolean switch.Code Snippets
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());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);
}
}public static void main(String[] args) {
double seconds = 35.079;
boolean isEcho = true;
Sonar sonar = new Sonar(Sonar.Medium.AIR, isEcho);
String verb = isEcho ? "echo" : "travel";
System.out.printf("The sound took %s seconds to %s and thus the distance is %s feet.\n",
seconds, verb, sonar.distance(seconds));
}Context
StackExchange Code Review Q#82323, answer score: 30
Revisions (0)
No revisions yet.