I'm trying to create a guitar program. I have a guitar amp class that has a sound object I'm trying to access in my pickup class. My goal is to set the sound property in my pickup class the same as my sound property in the GuitarAmp class so I can then set all the sound properties of my strings. I'm not really sure how to go about doing this and the articles I've read about gets and sets in Java have been no help. I have my two classes listed below, any help with the get and set would be appreciated.
public class GuitarAmp
{
// This is what I want to get from this class
public GuitarAmpSound sound;
public GuitarAmp(GuitarAmpSound sound, int volume, int distortSetting) {
sound = new GuitarAmpSound();
sound.setVolume(64);
sound.setDistortSetting(GuitarAmpSound.JAZZ);
}
public void changeVolume(int newVolume)
{
sound.setVolume(newVolume);
}
}
Here is the pickup class.
public class GuitarPickup {
public GuitarAmpSound pickupSound;
public void Connect(GuitarString strings[], GuitarAmp amp)
{
pickupSound = new GuitarAmpSound();
//This is where I need to set it
for(int i = 1; i <= 6; i++)
{
strings[i].setSound(pickupSound);
}
}
}
You need to declare a field (a variable belonging to a particular instance of a class) to hold each piece of information for that object. The pickupSound field on GuitarPickup is an example.
It is strong convention in Java to use the same name for the field as for the getters and setters. In the case of your volume, for example, the relevant part of the code would look like this:
public class GuitarAmpSound {
private int sound = 0;
public void setSound(int sound) {
this.sound = sound; // "this.sound" means the sound field, not the parameter
}
public int getSound() {
return sound; // or this.sound
}
}
If you want to implement the necessary code for your for loop, your GuitarString class needs a GuitarAmpSound field of its own named sound and a corresponding getter and setter.
As a note, the conditions in your for loop have a number of problems. Arrays in Java are zero-based (so the strings on a 6-string guitar would go from 0 to 5), and you should never hard-code array sizes in a loop but should use strings.length instead. Finally, Java has a more convenient syntax if you just want to retrieve each element in an array (or collection):
for(GuitarString string : strings) {
string.setSound(pickupSound);
}
Your code makes no sense, replace the GuitarAmp class by this:
public class GuitarAmp {
//This is what I want to get from this class
private GuitarAmpSound sound;
public GuitarAmp() {
sound = new GuitarAmpSound();
sound.setVolume(64);
sound.setDistortSetting(GuitarAmpSound.JAZZ);
}
public void changeVolume(int newVolume){
sound.setVolume(newVolume);
}
public GuitarAmpSound getSound() {
return sound;
}
public void setSound(Sound sound) {
this.sound = sound;
}
}
for get and set the rule is simple:
public YourClassName getYourObjectName() {
return yourObjectName;
}
public void setYourObjectName(YourClassName yourObjectName) {
this.yourObjectName = yourObjectName;
}
it's really complicated understand what you really wanna..take a look some change..but
I think you need to reestructure the objects. what you wanna do? can you explain better?
public class GuitarAmp {
//This is what I want to get from this class
public GuitarAmpSound sound;
--> the sound you pass before call the constructor
sound.setVoolume(x);
sound.setDistortSetting(Y)
so you pass the object sound with the attributes full of information
public GuitarAmp(GuitarAmpSound sound){
this.sound = sound;
}
public void changeVolume(int newVolume){
this.sound.setVolume(newVolume);
}
}
Here is the pickup class.
public class GuitarPickup {
public GuitarAmpSound pickupSound;
public void Connect(GuitarString strings[], GuitarAmp amp)
{
pickupSound = new GuitarAmpSound();
//This is where I need to set it
for(int i = 0; i<strings.length; i++)
{
amp.setSound(strings[i].getSound());
}
}
}
Conceptually, there is little point in saving the same Sound value to each GuitarString.
Related
I am trying to brushup java after a long time.
Any help is much appreciated.
For demonstration I have Animal Class that has an array of innerclass of Organs.
public class Animal
{
String nameOfAnimal;
Organs [] vitalOrgans = new Organs[3];
public Animal()
{
}
public String getNameOfAnimal() {
return nameOfAnimal;
}
public void setNameOfAnimal(String nameOfAnimal) {
this.nameOfAnimal = nameOfAnimal;
}
#Override
public String toString() {
return "Animal{" + "nameOfAnimal=" + nameOfAnimal + "}";
}
class Organs{
String nameOfOrgan;
public String getNameOfOrgan() {
return nameOfOrgan;
}
public void setNameOfOrgan(String nameOfOrgan) {
this.nameOfOrgan = nameOfOrgan;
}
#Override
public String toString() {
return "Organs{" + "nameOfOrgan=" + nameOfOrgan + '}';
}
}
}
Now in driver file when I make call there is no syntactical error but I get "Exception in thread "main" java.lang.NoSuchFieldError: vitalOrgans"
Animal mamal = new Animal();
mamal.setNameOfAnimal("Chimp");
mamal.vitalOrgans[0].setNameOfOrgan("Heart");
System.out.println(mamal.vitalOrgans[0].getNameOfOrgan());
What would be the way to make this (or similar idea) to work.
Thanks.
You would need to initialize the vitalOrgrans with new Organs(). Like:
public Animal() {
for (int i = 0; i < vitalOrgans.length; i++) {
vitalOrgans[i] = new Organs();
}
}
Because when you say :
Organs[] vitalOrgans = new Organs[3];
You are creating an array of 3 null Organs. Hence the null pointer exception, when accessing "vitalOrgans[i].".
Taking the relevant bit of code:
public class Animal
{
//...
Organs [] vitalOrgans = new Organs[3];
//...
}
Since your declaration of vitalOrgans was never given an access modifier (i.e. one of private, public, protected) it took on default access, which means only other classes in the same package can see it. Since your other block of code is not in the same package, it cannot see the field.
A minimally viable modification to just make it work would be to set the access to public:
public class Animal
{
//...
public Organs [] vitalOrgans = new Organs[3];
//...
}
While this works, it's not necessarily the best solution, as if you ever change how vitalOrgans is represented, or need to perform any validation, those edits would have to be done throughout the application. Thus, a better solution (and also, a major stylistic convention in Java for those exact reasons) is to make it (and all your fields, in fact) private and access via methods:
public class Animal {
private String nameOfAnimal;
private Organs[] vitalOrgans = new Organs[3];
//...
public Organs[] getVitalOrgans() {
return vitalOrgans;
}
//Alternative accessor that fetches only one organ.
public Organs getVitalOrgan(int index) {
if(index >= 0 && index < vitalOrgans.length)
return vitalOrgans[index];
else
return null;
}
public void setVitalOrgans(Organs[] vitalOrgans) {
this.vitalOrgans = vitalOrgans
}
//...
}
Your caller could then access Organs via either form of the get method (note, you probably want Organs to be public):
Animal.Organs futureMammalHeart = mamal.getVitalOrgan(0); //Animal.Organs due to Organs being an inner class.
if(futureMammalHeart != null) //Demonstration of null check. Safety first!
futureMammalHeart.setNameOfOrgan("Heart");
Animal.Organs[] mammalianVitalOrgans = mamal.getVitalOrgans();
if(mammalianVitalOrgans != null) //Just in case...
System.out.println(mamal.mammalianVitalOrgans[0].getNameOfOrgan());
Also, as Ari mentioned in his answer, don't forget to initialize the organs in your array, otherwise you will get a NullPointerException!
I'm working on a small project where I want to have a list of a class called "DevelopmentEmployee", but only one of them is allowed to manipulate certain methods in another class "Project". The way I have implemented it, the class Project has a field called projectLeader, which is of the type DevelopmentEmployee. When a DevelopmentEmployee attempts to access methods in the class Project, I want to check if the DevelopmentEmployee is equal to the specific instance of Project's projectLeader.
Something like
public class Project {
private DevelopmentEmployee projectLeader;
private List < Activity > activities = new ArrayList < Activity > ();
public Project(DevelopmentEmployee pL) {
this.projectLeader = pL;
}
public void addActivity(String activityName) {
if (projectLeader.equals(DevelopmentEmployee * ) {
activities.add(activity);
}
}
}
But I can't figure out a way to make the access requirement work. How can the instance of the class Project know who is trying to access it?
You should also pass the DevelopementEmployee in addActivity for checking it against the projectLeader.
public void addActivity(String activityName,DevelopmentEmployee employee) {
if (projectLeader.equals(employee) {
activities.add(activity);
}
}
Then you need to override equals method in DevelopmentEmployee class, for proper checking of equality, like the one as shown below :
public boolean equals(DevelopementEmployee e){
if(e!=null && this.employeeId==e.employeeId)
return true;
else
return false;
}
Several possibilities come to mind:
Provide the instance of the one accassing the project method to the method:
public void addActivity(String activityName, DevelpmentEmployee user) {
if (projectLeader.equals(user)) {`
Create some class that holds information about active user and use that inside the methods:
public class Project {
private UserRegistry userRegistry;
private List<Activity> activities = new ArrayList<Activity>();
public Project(UserRegistry userRegistry) {
this.userRegistry = userRegistry;
}
public void addActivity(String activityName) {
if (userRegistry.isActiveUserProjectLeader()) {
activities.add(activity);
}
}
}
public class UserRegistry {
private DevelpmentEmployee projectLeader;
private DevelpmentEmployee activeUser;
private List<DevelpmentEmployee> user;
public void addUser(DevelpmentEmployee user) { ... }
public void makeProjectLeader(DevelpmentEmployee newLeader) { ... }
public void makeActiveUser(DevelpmentEmployee newActiveUser) { ... }
public boolean isActiveUserProjectLeader() { ... }
}`
Given the following abstract class:
public abstract class BaseVersionResponse<T extends BaseVO> {
public abstract void populate(T versionVO);
}
and the following child class:
public class VersionResponseV1 extends BaseVersionResponse<VersionVOV1>
{
protected String testFieldOne;
protected String testFieldTwo;
public String getTestFieldOne() {
return testFieldOne;
}
public void setTestFieldOne(String value) {
this.testFieldOne = value;
}
public String getTestFieldTwo() {
return testFieldTwo;
}
public void setTestFieldTwo(String value) {
this.testFieldTwo = value;
}
#Override
public void populate(VersionVOV1 versionVO) {
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
I desire to do something like this from a calling method:
public void getVersionInfo(String version) {
BaseVO versionVO = null;
BaseVersionResponse<? extends BaseVO> baseVersionResponse = null;
baseVersionResponse = createVersionResponse(version);
versionVO = createVersionVO(version);
baseVersionResponse.populate(versionVO);
}
where createVersionResponse(...) and createVersionVO(...) look like this:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version) {
BaseVersionResponse<? extends BaseVO> specificVersionResponse = null;
if (version.equalsIgnoreCase("V1")) {
specificVersionResponse = new VersionResponseV1();
} else if (version.equalsIgnoreCase("V2"))
specificVersionResponse = new VersionResponseV2();
return specificVersionResponse;
}
public BaseVO createVersionVO(String version) {
BaseVO versionVO = null;
if (version.equalsIgnoreCase("V1")) {
versionVO = new VersionVOV1();
} else if (version.equalsIgnoreCase("V2"))
versionVO = new VersionVOV2();
return versionVO;
}
and VersionVOV1 looks like this:
public class VersionVOV1 extends BaseVO {
private String fieldOne = null;
private String fieldTwo = null;
private String fieldThree = null;
public String getFieldOne() {
return fieldOne;
}
public void setFieldOne(String fieldOne) {
this.fieldOne = fieldOne;
}
public String getFieldTwo() {
return fieldTwo;
}
public void setFieldTwo(String fieldTwo) {
this.fieldTwo = fieldTwo;
}
public String getFieldThree() {
return fieldThree;
}
public void setFieldThree(String fieldThree) {
this.fieldThree = fieldThree;
}
}
My problem arises when I try to compile this line of code:
baseVersionResponse.populate(versionVO);
in getVersionInfo(...). I'm getting a message that looks like this:
The method populate(capture#3-of ?) in the type BaseVersionResponse is not applicable for the arguments (BaseVO)
on the populate method above.
My thought was (which is apparently incorrect) that since the baseVersionResponse is, at this point in the code, actually a specific child instance, that the class would know exactly which populate method to call from that specific child class.
What am I doing wrong here? Is there a better way to do this if this isn't the correct approach?
Thank you for your time!
Ok, I took a better look at this today. The problem is that the wildcard, while the right way to go, precludes you from doing:
BaseVO versionVO = createVersionVO(version);
Because the populate call wants an extension of BaseVO, not an actual BaseVO, which doesn't qualify. That means you can't pass that versionVO variable directly.
So, to keep the type checking in place, which I think is good because you'll always want an implementation, leave pretty much everything as-is above, and change your BaseVersionResponse class to something like:
public abstract class BaseVersionResponse<T extends BaseVO> {
public T getVersion(BaseVO versionVO) {
try {
return (T) versionVO;
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}
}
public abstract void populate(BaseVO versionVO);
}
So, populate method now takes a BaseVO, and there's a new getVersion method to do some explicit casting for us. This should be ok since we know that the factory will always supply the right thing, but if another caller doesn't, an IllegalArgumentException is thrown.
Now, in your response class implementation, change the populate method accordingly:
public void populate(BaseVO version) {
VersionVOV1 versionVO = getVersion(version);
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
So, we've changed the populate method to take BaseVO, and the getVersion method does the casting for us. All the other type checks still apply, and we're good to go.
The casting makes it feel not as clean, but for the factory approach you're using, it's really the only way (I can think of) to keep the guarantees made by the type declarations and the code pattern in tact.
Hope that helps!
If you just take out the capture of type (the "<?>"), and leave it unchecked, it should work just fine. Even using type Object would have compiled.
But, given your specific example, what you probably want is the method:
public BaseVersionResponse<?> createVersionResponse(String version)
Changed to:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version)
Then, instead of using
BaseVersionResponse<?>
use
BaseVersionResponse<? extends BaseVO>
Since you know that the return type will be one of those things that implements the interface/class.
I have a Register class contains 8 sets& gets methods
using:
public class Register {
public Register(String Username) {
JFrame myFrame = new JFrame();
}
public void setUname() {
JoptionPane.showInputDialog(myFrame, "Enter Username");
}
public String getUname() {
return Uname;
}
}
There are other methods, 8 in total all requiring user input as String or double.
How in another class, can I import the methods into an ArrayList?
public class RegisterApp {
public addUser() {
ArrayList<Register> MyReg = new Arraylist<Register>();
myReg.add(Class Register);
}
}
Uncertain really of what goes after myReg.add
You need to add a reference to a Register.
public class RegisterApp {
public addUser() {
ArrayList<Register> MyReg = new Arraylist<Register>();
//Make an instance of Register and add it to the list
myReg.add(new Register("Me"));
}
}
You also mention adding methods to the list. What do you mean by that? What else are you trying to do? Do you want to call those methods on the instances in the list? You can do that like this:
for (Register reg : myReg) {
System.out.println(reg.getUname());
}
Note:
Your set method doesn't actually save the value anywhere. You are not storing the result in uname (which should be lowecase u). In general, setters are written so they are passed the new value in. This way you are not tied to using an input dialog anytime you change the name. That is a UI decision and should not effect the data model.
public void setUname(String uname) {
this.usname = uname;
}
For school I need to learn Java and since I'm used to C++ (like Cocoa/Objective-C) based languages, I get really frustrated on Java.
I've made a super-class (that can also be used as a base-class):
public class CellView {
public CellViewHelper helper; // CellViewHelper is just an example
public CellView() {
this.helper = new CellViewHelper();
this.helper.someVariable = <anything>;
System.out.println("CellView_constructor");
}
public void draw() {
System.out.println("CellView_draw");
}
public void needsRedraw() {
this.draw();
}
}
public class ImageCellView extends CellView {
public Image someImage;
public ImageCellView() {
super();
this.someImage = new Image();
System.out.println("ImageCellView_constructor");
}
public void setSomeParam() {
this.needsRedraw(); // cannot be replaced by this.draw(); since it's some more complicated.
}
#Override public void draw() {
super.draw();
System.out.println("ImageCellView_draw");
}
}
Now, when I call it like this:
ImageCellView imageCellView = new ImageCellView();
imageCellView.setSomeParam();
I get this:
CellView_constructor
ImageCellView_constructor
CellView_draw
However, I want it to be:
CellView_constructor
ImageCellView_constructor
CellView_draw
ImageCellView_draw
How can I do this?
Thanks in advance,
Tim
EDIT:
I also implemented this method to CellView:
public void needsRedraw() {
this.draw();
}
And this to ImageCellView:
public void setSomeParam() {
this.needsRedraw(); // cannot be replaced by this.draw(); since it's some more complicated.
}
And I've been calling this:
ImageCellView imageCellView = new ImageCellView();
imageCellView.setSomeParam();
Does this causes the problem (when I call a function from the super it calls to the super only)? How can I solve this... (without having to redefine/override the needsRedraw()-method in every subclass?)
You should get proper output.
I tried you example just commented unrelated things:
import java.awt.Image;
public class CellView {
//public CellViewHelper helper; // CellViewHelper is just an example
public CellView() {
//this.helper = new CellViewHelper();
//this.helper.someVariable = <anything>;
System.out.println("CellView_constructor");
}
public void draw() {
System.out.println("CellView_draw");
}
public static void main(String[] args) {
ImageCellView imageCellView = new ImageCellView();
imageCellView.draw();
}
}
class ImageCellView extends CellView {
public Image someImage;
public ImageCellView() {
super();
//this.someImage = new Image();
System.out.println("ImageCellView_constructor");
}
#Override public void draw() {
super.draw();
System.out.println("ImageCellView_draw");
}
}
and I get following output:
CellView_constructor
ImageCellView_constructor
CellView_draw
ImageCellView_draw
This is exactly what you want, and this is what your code print's.
The short answer is "you can't."
Objects are constructed from the bottom up, calling base class initializers before subclass initializers and base class consrtuctors before subclass constructors.
EDIT:
The code you have looks good, based on your edit. I would go through the mundane tasks like ensuring that you have compiled your code after you've added you System.out.println calls to your subclass