How to implement multiple subclasses with the same methods that use encapsulation? - java

I want to create a simple game in Java.
I'm struggling to understand how to use inheritance to accomplish how to implement subclasses that use encapsulation without needing to write out the same methods in the subclasses.
Ideally I'd like to make one base class "character" with a bunch of methods that use encapsulation, so that I can just declare different values for the private members of the subclasses. So something like,
public class Character {
private int hitPoints;
public int getHitPoints(){return hitPoints;}
}
And then just declare different values for the variables.
public class subCharacter extends Character {
private int hitPoints=100;
//getHitPoints() already inherited and should return 100
}
But to properly get the hit points of the subclass. I have to declare the same method in the subclass to actually get the method to work.
So isn't encapsulation incompatible with inheritance? Is there something basic here I'm misunderstanding or completely overlooking?

You should make the variable hitPoints protected in you Character class, and set it to 100 in the constructor of the subCharacter class. There is no need for the declaration of the getHitPoints method in the subclass. The code would look like this:
public class Character {
protected int hitPoints;
public int getHitPoints(){return hitPoints;}
}
public class subCharacter extends Character {
public subCharacter () {
hitPoints = 100;
}
}
Example of a subCharacter object:
subCharacter sub = new subCharacter();
System.out.println(sub.getHitPoints()); // prints 100

The reason this doesn't work like you think it should is because the subclass's hitpoints field is different from the superclass's hitpoints field. So while the superclass method is defined, it's trying to refer to a variable that you never actually initialized because it's not the same variable named hitpoints.
As others have already said, you should use the protected access modifier instead of the private access modifier on fields you want to have inherited to a subclass.
Then again, you probably don't actually need the SubCharacter class to begin with, if this is what you're actually writing for. You just need to have a constructor that takes a variable argument for hitpoints, or any other field in Character that needs to take different values.
//I'm not going to reproduce everything.
Character(int hp, String nm, boolean someBooleanThatIJustMadeUpToGetTheConceptAcross){
hitpoints = hp;
name = nm;
randomBoolean = someBooleanThatIJustMadeUpToGetTheConceptAcross;
}
This is not to say, however, that you don't need a superclass/subclass if, say, you're using this Character class for both enemies and player characters, for instance.
For an example of when you'd use inheritance...
public class Circle{
protected int radius;
Circle(){//It's always a good idea to have default constructors, by the way.
radius = 1;
}
Circle(int rad){
radius = rad;
}
}
public class Wheel extends Circle{
protected int numspokes;
Wheel(){
super(); //Calls the constructor for Circle, instead of reimplementing the wheel. badpuns++;.
numspokes = 0;
}
Wheel(int rad, int spokes){
super(rad); //This passes the radius up to the Circle this Wheel also is, so that any calls to this Wheel AS IF IT WAS a Circle, like an array or ArrayList of Circles, will function, which is the point of inheritance.
numspokes = spokes;
}
}

Related

Parameter not passed through the constructor

abstract class shape{
public double volume;
public double surface;
}
class cube extends shape{
public static double side;
public static double newSide;
cube(double newSide){
side = newSide;
}
public double volume(){
return side;
}
public double surface(){
return newSide;
}
}
public class shapes {
public static void main(String[] args) {
cube a = new cube(5);
System.out.println (a.volume);
System.out.println (a.surface);
}
}
This produces:
0.0
0.0
The parameter I am passing through the constructor does not seem to be processed properly by the cube class.
What am I doing wrong here?
So my guess is you haven’t figured out what objects are. If you look at the JDK code you will see examples of classes that define objects java.lang.String, java.lang.Integer, java.lang.StringBuilder are classes you can look at to get some idea of what objects are. Once you see how some of these classes work you can get the idea for the motivation behind the rest of this.
There are objects and there are classes. We use classes as templates to create objects. Each object has its own state. For example you can have many different strings in your program. Each string is an object with its own state, using its own instance variables. But static variables don’t belong to objects, they belong to the class.
“Instance” means one occurrence of an object. We instantiate objects using a constructor.
Your methods like
public double volume(){
are called accessors, or getters, because they’re used to access the state of the object.
Having an instance method accessor access a static variable is confusing. Static members have a different scope than instance members and combining them here is confusing. It’s hard to tell what is intended but you shouldn’t be using static variables to describe state that should be specific to an instance.
Your static variables are public and have the same name as the accessor. If you call the member without parens you are calling the variable directly. If you use parens you will call the accessor. .
In the event you do need static variables, you don’t initialize them in a constructor. Constructors are for initializing an instance of the class, where static variables don’t belong to one instance but to the class. Use constructors to set instance variables, not static ones.

Initialize superclass variables (needed in constructor) in a subclass

I'm writing a simple Asteroids-clone game, using Swing to display the graphics. I'm kind of following Derek Banas' tutorials, but decided to expand on my own.
The original idea is that every graphic element in the game (i.e. the Asteroids, the Spaceship and the Bullets) extends the Polygon class. Their constructor would look something like this:
public class SpaceShip extends Polygon {
//x and y coordinates
public static int[] polyXArray = {...};
public static int[] polyYArray = {...};
//other class variables
{...}
public SpaceShip() {
super(polyXArray, polyYArray, polyXArray.length);
}
}
And it will be similar for the other graphic elements.
EDIT: The key element here is that the two arrays don't store the actual coordinates of the objects, but their position relative to their centre, whose coordinates are double-type class-variable. Thus, the arrays describe just the shape of the object, while the subclass move() method will affect the centre's coordinates. The class responsible for the actual drawing will call the move() method and then apply an affine transform to move and rotate the shape (according to a properly defined angle parameter). I'm doing this to avoid precision problems related to dealing with double arithmetic.
Now, since the elements share a lot of "equal" variables (their centre coordinates, which I need in order to translate them with an affine transform, their speed components etc...) and methods (getters and setters, move() methods, etc...) I thought about making them be the extension of an abstract class - say, GameShape - which holds all these common methods and variables. GameShape would now be the one extending Polygon directly:
public abstract class GameShape extends Polygon {
//x and y coordinates, still unassigned
public static int[] polyXArray, polyYArray;
//other class variables
{...}
public GameShape() {
super(polyXArray, polyYArray, polyXArray.length);
}
}
Then, I'd want to assign the desired value to polyXArray and polyYArray when I define the different subclasses in order to draw the different shapes I need, but I haven't been able to find a way to do it.
I do want those variable to be static because they are specific properties of the single classes, and I wouldn't want to pass them as a parameter every time I instantiate a new object.
My situation is very similar to the one described in this question, but the proposed solution doesn't seem to work, since I need those very variables in the constructor. Is there a way to get over - or around - this problem? Regardless of the procedure, my main aim is to have a superclass common to all the graphic elements, in order to avoid tens of lines of copy-pasted code.
You have pairs of arrays that describe the shapes of specific kinds of game objects. If different game objects can have different shapes, then they cannot all share a single pair of arrays, as would be the case if they were static properties of a common superclass of all the game object classes. Different objects of the same kind can share the same pair of arrays (supposing that those don't need to be modified on a per-object basis), which could correspond to those arrays being static fields of the concrete game object classes. In that case, however, if you want a superclass of those classes to be able to access the correct shape data for a given game object, then it has to be told what those shape data are.
There are two main ways you could do that:
You could pass the appropriate shape arrays to the superclass's constructor. You say you don't want to do this, but I don't understand why.
You could define accessor methods on the superclass that the subclasses are supposed to override to provide the correct shape data (this is called the Template Method pattern).
The solution from this question will work if your classes will NOT extend shape, but provide shapes via accessor + private static field.
public abstract class GameObject {
...
public abstract Polygon getShape();
This also helps to escape shapes duplication.
If you really do want to initialize things in your constructor, just call the empty super(); and then loop against abstract getPolyXArray() and getPolyYArray() to feed addPoint.
public abstract class GameShape extends Polygon {
public GameShape() {
super();
final int length = getPolyXArray().length;
for (int i = 0; i < length; i++) {
addPoint(getPolyXArray()[i], getPolyYArray()[i]);
}
}
public abstract int[] getPolyXArray();
public abstract int[] getPolyYArray();
//common stuff...
}
public class Asteroids extends Polygon {
public int[] getPolyXArray() { return new int[]{1, 2, 3}; }
public int[] getPolyYArray() { return new int[]{1, 2, 3}; }
}
The array fields cannot be static because different shapes have different coordinates. Also you don't need these arrays in the specific subclasses because they are already in Polygon or GameShape.
Here is more-or-less how I would write GameShape (although I agree with #Michael that you don't need to pass both polyXArray and polyXArray.length to the constructor).
public abstract class GameShape extends Polygon {
// I got rid of the array fields as I think they are in Polygon anyway.
//other class variables
{...}
// I added arguments to your constructor.
public GameShape(int[] polyXArray, int[] polyYArray) {
super(polyXArray, polyYArray, polyXArray.length);
}
}
The trouble is that super must be the first line of a constructor, but you can do it using private methods to build the arrays:
public final class BoringRectangle extends GameShape {
public BoringRectangle(int left, int right, int top, int bottom) {
super(xArray(left, right), yArray(top, bottom));
}
private static int[] xArray(int left, int right) {
return new int[] {left, right, right, left};
}
private static int[] yArray(int top, int bottom) {
return new int[] {bottom, bottom, top, top};
}
}
I would think that polyXArray and polyYArray reside in the Polygon class; that's where they belong. Therefore it's not a good idea to have duplicate fields. Also, get rid of the ned to call the super constructor. I would design the class structure like this:
public class SquareShape extends Polygon {
private int size;
public SquareShape(int x, int y, int size) {
this.size = size;
int[] xpoints = new int[4]{
x - size / 2,
x - size / 2,
x + size / 2,
x + size / 2
};
int[] ypoints = new int[4]{
y - size / 2,
y + size / 2,
y + size / 2,
y - size / 2
};
setXArray(xpoints);
setYArray(ypoints);
}
}
This way, you can ensure that all SquareShape objects do indeed have a square shape, but you can customize things you should be able to customize. Like position and size, which should not be static shared fields. setXArray and setYArray should be protected methods residing in Polygon. You don't want the outside world messing with the individual points. You can add public getters, although.
NOTE
You may want to consider using a single array of a complex Point type, rather then two tightly coupled and dependent arrays. I feel like this will greatly simplify a lot of tasks in your project.
EDIT:
As VGR stated in the comments, this will not compile. So, we will have to change the implementation a little, namely, we will use the HAVE relationship instead of IS relationship :-)
First of all, do not make the poly array fields static. If you do, they will be the same for all of the subclasses as well, so what is the point?
Secondly, use a template method design pattern here. Your class will look something like this:
public abstract class GameShape {
//x and y coordinates, still unassigned
public int[] polyXArray, polyYArray;
private Polygon polygon;
//other class variables
{...}
public GameShape() {
instantiatePolyArrays();
this.polygon = new Polygon(polyXArray, polyYArray, polyXArray.length);
}
protected abstract void instantiatePolyArrays();
public final Polygon getPolygon(){
return this.polygon;
}
}
Every extending class will have to override this method and you can instantiate the arrays for each of the classes in each of the method overrides.
Also, a word about the IS-HAVE relationship problem - what you presented in your example is a IS relationship, in which the GameShape object IS a Polygon, hence the need to call the super constructor and the problem with that. In my solution this is replaces by a HAVE relationship, in which the GameShape object HAS a Polygon object inside, accessed with a getPolygon() method. This allows you to have lots of additional flexibility :-)

Should I declare variables in the class, if the class has only a constructor?

Let's say I have a class:
public class Foo {
private int x;
private int y;
public Foo(int x, int y) {
this.x = x;
this.y = y;
/**
* here comes a lot of code within this constructor
* that uses these x and y variables.
*/
}
}
I understand, that if I had some other methods in this class that would use the x and y variables, I should have copied the constructor's arguments into the fields like I did above, but what if I don't have any other methods but only the constructor? Should I still create the fields or my class should look like this:
public class Foo {
public Foo(int x, int y) {
/**
* here comes a lot of code within this constructor
* that uses these x and y variables.
*/
}
}
What is the right style?
UPDATE
Sorry, I was wrong by thinking that there is a some general pattern of doing this, that's why I gave some idle example. I still will not copy-paste my code, because the project is too big and a single class out of context will not make any sense. But here's a more specific example:
import javax.swing.JLabel;
import javax.swing.JPanel;
public class InformationPanel extends JPanel {
private JLabel nameLbl = new JLabel();
public InformationPanel(Student student) {
nameLbl.setText(student.getName());
this.add(nameLbl);
}
}
So in this case should I have a local field
private Student student;
And then:
this.student = student;
Or I shouldn't?
A constructor is used to initialize the state of an object. Based on your question, your object has no state.
Your constructor accepts some parameters which are only used inside the constructor. Your constructor doesn't produce any output. Although I don't know what logic you have inside this constructor, it seems like you are using the constructor as if it was a static method. Why not put your logic in a static method?
The first is the preferred style. However, the answer for this case is probably: use a static method, don't use a constructor.
If you want just the functionality that's encoded in the constructor method, then a static method is the way to go.
As a constructor is used to create a new instance of a class, which combines functionality (via other methods) and state (via fields) it's hard to see how a stateless, methodless instance would be much use. Hence the guess on my part is that what you're after is:
public class Foo {
public static void doSomething(int x, int y) {
/**
* here comes some code within this method
* that uses these x and y variables.
*/
}
}
The last part being - don't put a lot of code in a single method, unless it really belongs there. Think modularly and decompose the method into parts each of which may be tested.
You should not store the values in fields if they are only used in the constructor.
However, more importantly what you are doing is not appropriate for a constructor. As the resulting object created seems fairly useless.
Don't see why you need a class to achieve what you are trying to do. Depending on your use case it either should be a method in another class or a Utility Class containing static methods. But it all depends on what you are trying to do or the context.

In which situations we make variables as public and methods as private?

Currently I am learning basics of java and C++. I have read in book Let Us C++, that in almost every case we we make instance variables private and methods public for the security purposes. But it is also mentioned in this book that in some cases we make variables public and methods private..
I am continuously thinking, in which cases we will do so. Can anyone please explain this.
Private methods (or private member functions in C++ terminology) are mostly useful as helper functions. For example, think of the case that you want to implement fractions, but want to ensure that your fraction is always normalized. Then you could use a private member function normalize() which normalizes your fraction, and which is called after each operation which might result in a non-normalized fraction, for example (C++ code):
class Fraction
{
public:
Fraction(int num, int den = 1);
Fraction operator+=(Fraction const& other);
Fraction operator*=(Fraction const& other);
// ...
private:
int numerator, denominator;
};
Fraction::Fraction(int num, int den):
numerator(num),
denominator(den)
{
normalize();
}
Fraction Fraction::operator+=(Fraction const& other)
{
int new_den = denominator*other.denominator;
numerator = numerator*other.denominator + denominator*other.numerator;
denominator = new_den;
}
Fraction Fraction::operator*=(Fraction const& other)
{
numerator *= other.numerator;
denominator *= other.denominator;
normalize();
}
void Fraction::normalize()
{
int factor = gcd(numerator, denominator);
numerator /= factor;
denominator /= factor;
}
Another, C++ specific use of private functions is based on the fact that in C++ private is only about access control, not about visibility. This enables to do unoverridable pre-post-condition checking in the base class while making the actual function virtual:
class Base
{
public:
foo frobnicate(some arguments);
private:
virtual foo do_frobnicate(some arguments) = 0;
};
foo Base::frobnicate(some arguments)
{
check_precondition(arguments);
foo result = do_frobnicate(arguments);
check_post_condition(foo);
return foo;
}
Classes derived from Base will override do_frobnicate, while users will call frobnicate which always checks the pre/postconditions no matter what the derived class does.
Generally static final variables are public in a class. If you don't need to change the value of that variable and want other classes to access it then you make it public static final.
Private methods are used only within the class for doing the task, which is internal to that class. Like a utility method or some business calculation method. Or simply to break the code of public method into multiple private methods, so that methods don't grow too big.
When a method is to be used by other methods(public) of the class and you do not want the object to access that method directly, we make that method as private.
And in some cases, if you want to access your variable directly from the class object, then make it public.
If you don't need the varibale or methode in other classes don't make it public. This goes for methodes and variables.
private methods are for the internal use of the class. They can be called from other public classes. Those are private because you encapsualted from outer world.
For example
public void method1(){
method2();
}
private void method2(){
// for internal use
}
Public variables are mainly used for class variables in which cases there is no harm of direct accessing the variables from outside. For example
public static final int FLAG = true;
You can directly call the variable from outside.
It depends how much security you want for each class.
For example, if you have a Vector class, that only has 3 variables x, y and z, you should make them public. Many classes will probably use the Vector class and it's fine if they change values in it.
If you have a Person class that stores credit card number, background record, address etc, you should make them private to avoid security issues.
However, if you have all variables as private, and you provide accessors and mutators for all of them, you're effectively making them just like public (but with more work).
EDIT:
All constant variables should be public, because you cannot change them anyway.
Static variables could be both, depending on a situation. Probably better to have static get and set functions for static variables.
Private variables or functions can be use only in the class where they are declarated.
Public variables or functions can be use everywhere in your application.
So you should declarate private all those variables and functions that you are going to use ONLY in the class where they belong.
Example:
public class Car {
private String model;
public setModel(String model) {
if (model != null)
this.model = model;
}
public getModel() {
return model;
}
private doSomething() {
model = "Ford";
}
}
In the class Car we declarate the String model as private because we are going to use it only in the class Car, doing this we assure that other classes couldn't change the value of this String without using the function setModel.
The functions setModel and getModel are public, so we can access the private variable model from other classes ONLY using those methods.
In this example, the function setModel checks if the value its null, in which case it doesn't set the value. Here you can see that if you had declarated the String model as public, you wouldn't have control over what value it's being recorded.
The function doSomething is private and other classes can't use it. For other side, like this function is private and it belong to the same class where is the String model, it can change its value without using the method setModel.
A rule of thumb, you make methods public when it is okay for other classes to access them. internal methods or helper methods should either be protected or private.Protected if you want the method to be extendable by those extending your class however if you don't want this just mark them private.

How to use a private method in Java

I am given a class that has a private method say setCoors(int x, int y). The constructor of that class has the setCoors in it too. In a different class, I want to have a method setLocation which calls setCoors. Is this possible?
New Question:
If I am not allowed to set the method to public, is this possible?
public class Coordinate{
public Coordinate(int a, int b){
setCoors(a,b)
}
private void setCoords(int x, int y)
}
public class Location{
private Coordinate loc;
public void setLocation(int a, int b)
loc = new Coordinate(a,b)
}
The best and most helpful answer depends on the context of the question, which is, I believe, not completely obvious.
If the question was a novice question about the intended meaning of private, then the answer "no" is completely appropriate. That is:
private members of A are accessible only within class A
package-private members of A are accessible only within classes in A's package
protected members of A are accessible only within classes in A's package and subclasses of A
public members of A are accessible anywhere A is visible.
Now, if, and okay maybe this is a stretch (thank you Brian :) ), that the question came from a more "advanced" context where one is looking at the question of "I know private means private but is there a language loophole", then, well, there is such a loophole. It goes like this:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
class C {
private int x = 10;
private void hello() {System.out.println("Well hello there");}
}
public class PrivateAccessDemo {
public static void main(String[] args) throws Exception {
C c = new C();
List<Field> fields = Arrays.asList(C.class.getDeclaredFields());
for (Field f: fields) {
f.setAccessible(true);
System.out.println(f.getName() + " = " + f.get(c));
}
List<Method> methods = Arrays.asList(C.class.getDeclaredMethods());
for (Method m: methods) {
m.setAccessible(true);
m.invoke(c);
}
}
}
Output:
x = 10
Well hello there
Of course, this really isn't something that application programmers would ever do. But the fact that such a thing can be done is worthwhile to know, and not something that should be ignored. IMHO anyway.
No, private means the method can only be called inside of the Class in which it is defined. You will probably want to have setLocation create a new instance of the class setCoords resides in, or change the visibility on setCoords.
EDIT: The code you have posted will work. Just be aware that any instance of the Location class will be bound to its own Coordinate object. If you create a new Coordinate object somewhere else in your code, you will be unable to modify its internal state. In other words, the line
Coordinate myCoord = new Coordinate(4, 5);
will create the object myCoord which will forever have the coordinates 4 and 5.
private means it's private
If you want other classes to call it, maybe you shouldn't make it private?
No private methods can't be accessed outside the class in which they are defined
Kid-doing-homework: the answer is no. Guy-requiring-some-crazy-work-around-for-his-job: the answer is yes. Far more importantly though, Your setCoors method should not take int arguments. It should take two SilverBullet objects.
private means you can only access it inside the class defined.

Categories

Resources