Related
I have an object, let's call it a Request, that has associations to several other objects like:
Employee submitter;
Employee subjectsManager;
Employee pointOfContact;
And several value properties like strings, dates, and enums.
Now, I also need to keep track of another object, the subject, but this can be one of 3 different types of people. For simplicity let's just talk about 2 types: Employee and Consultant. Their data comes from different repositories and they have different sets of fields, some overlapping. So say an employee has a
String employeeName;
String employeeId;
String socialSecurityNumber;
Whereas a consultant has
String consultantName;
String socialSecurityNumber;
String phoneNumber;
One terrible idea is that the Request has both a Consultant and an Employee, and setSubject(Consultant) assigns one, setSubject(Employee) assigns the other. This sounds awful. One of my primary goals is to avoid "if the subject is this type then do this..." logic.
My thought is that perhaps an EmployeeRequest and a ConsultantRequest should extend Request, but I'm not sure how, say, setSubject would work. I would want it to be an abstract method in the base class but I don't know what the signature would be since I don't know what type the parameter would be.
So then it makes sense to go at it from an interface perspective. One important interface is that these Request objects will be passed to a single webservice that I don't own. I will have to map the object's fields in a somewhat complex manner that partially makes sense. For fields like name and SSN the mapping is straightforward, but many of the fields that don't line up across all types of people are dumped into a concatenated string AdditionalInfo field (wump wump). So they'll all have a getAdditionalInfo method, a getName, etc, and if there's any fields that don't line up they can do something special with that one.
So that makes me feel like the Request itself should not necessarily be subclassed but could contain a reference to an ISubjectable (or whatever) that implements the interface needed to get the values to send across the webservice. This sounds pretty decent and prevents a lot of "if the subject is an employee then do this..."
However, I would still at times need to access the additional fields that only a certain type of subject has, for example on a display or edit page, so that brings me right back to "if subject is instance of an employee then go to the edit employee page..." This may be unavoidable though and if so I'm ok with that.
Just for completeness I'll mention the "union of all possible fields" approach -- don't think I'd care to do that one either.
Is the interface approach the most sensible or am I going about it wrong? Thanks.
A generic solution comes to mind; that is, if the language you're using supports it:
class Request<T extends Subject> {
private T subject;
public void setSubject(T subject) {
this.subject = subject;
}
public T getSubject() {
return subject;
}
}
class EmployeeRequest extends Request<Employee> {
// ...
}
class ConsultantRequest extends Request<Consultant> {
// ...
}
You could similarly make the setSubject method abstract as you've described in your post, and then have separate implementations of it in your subclasses. Or you may not even need to subclass the Request class:
Request<Employee> employeeRequest = new Request<>();
employeeRequest.setSubject(/* ... */);
// ...
int employeeId = employeeRequest.getSubject().getEmployeeId();
To elaborate on my question, the particular situation is this:
If I have a simulation or game project with, say, a Monster class that has different statistics as member data (hitPointsRemaining, AttackDamage, etc) and I want to have any number of different types of monsters with constant base statistics (MaxHP, Speed, etc), then I see three ways that this class will need to be used:
An actual class with an interface to be used for using Monster objects throughout the code (say, "Monster")
The actual "data" for the different types of monsters. (conceptually possible subclasses? although I'm certain that's not the right solution) example: Goblin, Dragon, Cyclops, etc
Actual instantiated Monster objects representing different monsters as the character meets them in the game (with possibility of multiple instances of the same type at any time)
I was wondering how most designers go about implementing this.
My thoughts were as follows:
-It doesn't make sense to make a Monster class and then a new subclass for every type of monster conceived of as development progresses. This seems like a horribly messy and unmaintainable solution, especially if the number of different monster types vary in the hundreds and difference between each type isn't nearly great enough to warrant a new subclass
-Rather, my solution would be as follows:
1. Have a file that can be added to containing data for all the different Monster types and their characteristics in a table. The table could be added to at any time in the development of the project.
Write a function to load data from the table into a Monster object.
Write an initialization call at the start of the program, possibly in some sort of MonsterManager class, to parse the file and create a static or member vector of instantiated Monster objects with all the "base" statistics filled in from the table in the file (ie, starting hitpoints, etc)
Whenever I want to instantiate a new Monster of some type to add to someone's army or have someone meet with, choose a Monster out of the vector (randomly or via some detemining factor) create a new Monster object, and copy it out of the vector
Does this make sense as a solution or am I out to lunch? If this is not a good solution, what better methods are there?
Other supplemental questions:
-Would it make sense to make a different class for the monster data that would be held in the vector? I thought I could have a class called MonsterData that would be built into a vector by the MonsterManager above. I could pass to a MonsterData object to the constructor of the Monster class to actually create Monster objects, since a lot of Monster objects' characteristics would be determined by their monster-types (MaxHP, speed, etc) and other stuff would vary (CurrentHP, any randomized variables, etc)
-I thought this method would be optimizable since you could do things like add an entry to the table indicating which levels the monsters show up in, and then have the MonsterManager initialization function only load all monsters from certain levels at once to shrink the memory footprint)
-Since I'm not using an enum for this, does storing a text string make sense as a means of identifying the Monster object's "type"? Perhaps a pointer to the Monster (or MonsterData) it was copied from in the MonsterManager's vector would be better?
I used the game analogy because it is what makes the most sense to me here, but I'd like to know the best design pattern for this kind of thing in any situation.
Thanks everyone!
Inheritance should be used for modifying/adding behaviour, not for varying data values. In your example, it seems that each monster is defined by a set of attributes (HP, attack etc.) and you want to instantiate different monster types within the game. You don't really need inheritance for this.
You're on the right track with your MonsterData class; here's how I would go about it (mostly just different names for classes which I think are more meaningful):
// This is what you called MonsterData
// It describes how to create a monster of a specific type
public class MonsterDescription {
private String type; // eg. "Goblin"
private int maxHitPoints;
private int speed;
...
}
// This is an "active" instance of a monster
public class Monster {
private int currentHitPoints;
...
// static factory method
public static Monster create(MonsterDescription desc) {
...
}
}
// This is kind of what you called MonsterManager
// Contains a collection of MonsterDescription, loaded from somewhere
public class MonsterDescriptionRepository {
// finds the description for a given type of monster
public MonsterDescription find(String type) {
...
}
}
And then here's how you would instantiate a new monster:
MonsterDescription desc = repository.find("Goblin");
Monster monster = Monster.create(desc);
the dataloader approach seems to fit your problem - it makes it easily extendable.
i would recommend to create subclasses for diferrent functionalities - for example, create a FlyingMonster subclass which will handle Dragon but not Goblin or Shark
this way you can (try) to avoid having a single Monster class which can fly/run/dive ;)
your last question was about external data keying - for this i think the pointer approach would be the best:
it's unique
it can help debugging
you can optionally use the stored values from the store
it will show the 'is_a' connection to the ancestor
note: i don't think you should 'care' with any performance issues (load them into memory to reduce memory footprint) at this stage, because it's usually breaks the design
I have read in many places that "getters and setters are evil". And I understood why so. But I don't know how to avoid them completely. Say Item is a class that has information about item name, qty, price etc...
and ItemList is a class, which has a list of Items. To find the grand total:
int grandTotal()
{
int total = 0;
for (Item item: itemList)
total += item.getPrice();
return total;
}
In the above case, how does one avoid getPrice()? The Item class provides getName, setName, etc....
How do I avoid them?
When should you use getters and setters?
Getters and setters are great for configuring or determining the configuration of a class, or retrieving data from a model
Getting the price of an item is an entirely reasonable use of a getter. That is data that needs to be available and may involve special considerations to protect the data by adding validation or sanitization to the setter.
You can also provide getters without setters. They do not have to come in pairs.
When shouldn't you use getters and setters?
Sometimes objects rely on internal properties that will never be exposed. For example, Iterators and internal collections. Exposing the internal collection could have dramatically negative and unexpected consequences.
Also, for example, let's say you are communicating via some HttpURLConnection. Exposing the setter for your HttpURLConnection means that you could end up with a very odd state should the connection be changed while waiting to receive data. This connection is something that should be created on instantiation or entirely managed internally.
Summary
If you have data that is for all intents and purposes public, but needs to be managed: use getters and setters.
If you have data that needs to be retrieved but under no circumstances should ever be changed: use a getter but not a setter.
If you have data that needs to be set for internal purposes and should never be publicly exposed (and cannot be set at instantiation): use a setter but not a getter (setter presumably prevents a second call affecting the internal property)
If you have something that is entirely internal and no other class needs to access it or change it directly, then use neither.
Don't forget that setters and getters can be private and even for internally managed properties, having a setter that manages the property may be desirable. For example, taking a connection string and passing it to the setter for HttpURLConnection.
Also note:
Allen Holub's article Why getter and setter methods are evil seems to be the source of OP's reasoning but, in my opinion, the article does a poor job of explaining its point.
Edit: Added summary
Edit 2: spelling corrections
It's a shame to see a small, vocal minority take a back lash against the whole "Getters and Setters" are evil debate. Firstly the article title is purposely provocative to draw you in, as should any blog post. I've in turn blogged about this before and several years later updated my opinions and ideas about this question. I'll summarise the best I can here.
Getters and setters (accessors) are not evil
They are "evil" (unnecessary) most of the time however
Encapsulation is not just adding accessors around private fields to control change, after all there is no benefit to added get/set methods that just modify a private field
You should write as much code as possible with the principle of "Tell, Don't Ask"
You need to use accessors for framework code, DTOs, serialisation and so forth. Don't try to fight this.
You want your core domain logic (business objects) to be as property free as possible however. You should tell objects to do stuff, not check their internal state at will.
If you have a load of accessors you essentially violate encapsulation. For example:
class Employee
{
public decimal Salary { get; set; }
// Methods with behaviour...
}
This is a crap domain object, because I can do this:
me.Salary = 100000000.00;
This may be a simple example, but as anyone who works in a professional environment can attest to, if there is some code that is public people will make use of it. It would not be wrong for a developer to see this and start adding loads of checks around the codebase using the Salary to decide what do with the Employee.
A better object would be:
class Employee
{
private decimal salary;
public void GivePayRise()
{
// Should this employee get a pay rise.
// Apply business logic - get value etc...
// Give raise
}
// More methods with behaviour
}
Now we cannot rely on Salary being public knowledge. Anyone wanting to give a pay rise to employees must do this via this method. This is great because the business logic for this is contained in one place. We can change this one place and effect everywhere the Employee is used.
The following sample is a brilliant example of boilerplate setters and getters.
class Item{
private double price;
public void setPrice(final double price){
this.price = price;
}
public double getPrice(){
return this.price;
}
}
Some coders think that this is called encapsulation, but in fact this code is exact equivalent of
class Item{
public double price;
}
In both classes price is not protected or encapsulated, but the second class reads easier.
class Item{
private double price;
public void setPrice(final double price){
if(isValidPrice(price))
this.price = price;
else throw new IllegalArgumentException(price+" is not valid!");
}
public double getPrice(){
return this.price;
}
}
This is a real encapsulation, the invariant of the class is guarded by the setPrice. My advice - don't write dummy getters and setters, use getters and setters only if they guard the invariant of your class
I have read in many places that "getters and setters are evil".
Really? That sounds crazy to me. Many? Show us one. We'll tear it to shreds.
And I understood why so.
I don't. It seems crazy to me. Either your misunderstood but think you did understand, or the original source is just crazy.
But I don't know how to avoid them completely.
You shouldn't.
how to avoid getPrice?
See, why would you want to avoid that? How else are you suppose to get data out of your objects?
how to avoid them???
Don't. Stop reading crazy talk.
When someone tells you that getters and setters are evil, think about why they are saying that.
Getters
Are they evil? There is no such thing as evil in code. Code is code and is neither good nor bad. It's just a matter of how hard it is to read and debug.
In your case, I think it is perfectly fine to use a getter to calculate the final price.
The "evil"
Usecase: you think you want the price of an item when buying something.
People sometimes use getters like this:
if(item.getPrice() <= my_balance) {
myBank.buyItem(item);
}
There is nothing wrong with this code, but it isn't as straight-forward as it could be. Look at this (more pragmatic approach):
myBank.buyItem(item); //throws NotEnoughBalanceException
It's not the buyers or the cashiers job to check the price of an item when buying something. It's the actually the bank's job. Imagine that customer A has a SimpleBank.java
public class SimpleBank implements Transaction {
public void buyItem(Item item){
if(getCustomer().getBalance() >= item.getPrice()){
transactionId = doTransaction(item.getPrice());
sendTransactionOK(transactionId);
}
}
}
The first approach seems fine here. But what if customer B has a NewAndImprovedBank.java?
public class NewAndImprovedBank implements Transaction {
public void buyItem(Item item){
int difference = getCustomer().getBalance() - item.getPrice();
if (difference >= 0) {
transactionId = doTransaction(item.getPrice());
sendTransactionOK(transactionId);
} else if (difference <= getCustomer().getCreditLimit()){
transactionId = doTransactionWithCredit(item.getPrice());
sendTransactionOK(transactionId);
}
}
}
You might think that you are being defensive when using the first approach, but actually you are limiting the capabilities of your system.
Conclusion
Don't ask for permission aka item.getPrice() , ask for forgiveness aka NotEnoughBalanceException instead.
getPrice() is accessing a private variable I'm assuming.
To answer your question directly, make the price variable public, and code something like (syntax may differ depending on language, use of pointers etc):
total += item.price;
However this is generally considered bad style. Class variables should generally remain private.
Please see my comment on the question.
How to avoid getters and setters? Design classes that actually act upon the data they hold.
Getters lie about the data anyway. In the Item.getPrice() example, I can see I'm getting an int. But is the price in dollars or cents? Does it include tax(es)? What if I want to know the price in a different country or state, can I still use getPrice()?
Yes, this might be beyond the scope of what the system is designed to do, and yes, you might just end up returning a variable's value from your method, but advertising that implementation detail by using a getter weakens your API.
'Evil' as .getAttention()
This has been discussed often, and even perhaps went a bit viral, as a result of the pejorative term "Evil" used in the dialog. There are times when you need them, of course. But the problem is using them correctly. You see, Professor Holub's rant isn't about what your code is doing now, but about boxing yourself in so that change in the future is painful and error prone.
In fact, all I have read by him carries this as its theme.
How does that theme apply to the class Item?
A look at the future of Item
Here is fictions's item class:
class Item{
private double price;
public void setPrice(final double price){
if(isValidPrice(price))
this.price = price;
else throw new IllegalArgumentException(price+" is not valid!");
}
public double getPrice(){
return this.price;
}
}
This is all well and good- but it is still 'Evil' in the sense that it could cause you a lot of grief in the future.
The grief is apt to come from the fact that one day 'price' may have to take different currencies into account (and perhaps even more complex barter schemes). By setting price to be a double, any code that is written between now and the 'apocalypse' (we're talking evil, after all) will be wiring price to a double.
It is much better (even Good, perhaps) to pass in a Price object instead of a double. By doing so you can easily implement changes to what you mean by 'price' without breaking the existing interfaces.
The takeaway on getters and setters
If you find yourself using getters and setters on simple types, make sure you consider possible future changes to the interface. There is a very good chance you shouldn't be. Are you using setName(String name)? You should consider setName(IdentityObject id) or even setIdentity(IdentityObject id) in case other identification models show up (avatars, keys, whatever). Sure you can always go around and setAvatar and setKey on everything, but by using an object in your method signature you make it easier to extend in the future to the objects that can use the new identity properties and not break the legacy objects.
A different perspective that is missing here so far: getters and setters invite to violate the Tell Don't Ask principle!
Imagine you go shopping in the supermarket. In the end, the cashier wants money from you. The getter/setter approach is: you hand over your purse to the cashier, the cashier counts the money in your purse, takes the money you owe, and gives back the purse.
Is that how you do things in reality? Not at all. In the real world, you typically don't care about the internal state of "autonomous" other "objects". The cashier tells you: "your bill is 5,85 USD". Then you pay. How you do that is up to you, the only thing the cashier wants/needs is he receives that amount of money from your side.
Thus: you avoid getters and setters by thinking in terms of behavior, not in terms of state. Getters/setters manipulate state, from the "outside" (by doing avail = purse.getAvailableMoney() and purse.setAvailableMoney(avail - 5.85). Instead, you want to call person.makePayment(5.85).
How to avoid getters and setters in Java?
Use Project Lombok
Cloudanger answer is is one, but you must also realize that the item list will likely contain many item objects with quantity ordered on it.
Solution : create another class in between them that stores your item in the item list and the qty ordered for that item (Let's say the class is called OrderLine).
OrderLine will have Item and qty as fields.
After that, code something like calculateTotal(int qty) in Item which return price*qty.
Create a method in OrderLine that call calculateTotal(qtyOrdered)
Pass the return value to the itemList.
This way, you avoid getters.
The ItemList will only know the total price.
Your code should live with your data.
Ask the Object who has the data to calculate the totalPrice instead of asking that object for raw data to calculate your totalPrice.
Really?
I don't think that. on the contrary the getters and setters help you to protect the consistense of the variables.
The importance of getters and setters is to provide protection to private attributes so that they can not be accessed directly for this it is best that you create a class with the attribute item in which you include the corresponding get and set.
Use a helper class ShoppingCart. Item's method item.addTo(ShoppingCart cart) would add the price to the totalSum of the cart using shoppingCart.addItem(Item item, int price)
Dependency from Item to ShoppingCart isn't disadvantageous if the Items are meant to be items of ShoppingCarts.
In the case where Items live solely for the ShoppingCart and the Item class is small, I would more likely have the Item as an inner class of the ShoppingCart, so that the ShoppingCart would have access to the private variables of the items.
Other thoughts
It would also be possible, although quite unintuitive design, to have the Item class count the sum (item.calculateSum(List<Item> items)), since it can access the private parts of other items without breaking encapsulation.
To others wondering why the getters are bad. Consider the given example where the getPrice() returns integer. If you would want to change that to something better like BigDecimal at least or a custom money type with currency, then it wouldn't be possible since the return type int exposes the internal type.
Getters and setters are evil because they break encapsulation and can unnecessarily expose an objects internal state and allow it to be modified in way it should not be. The following article elaborates on this problem:
http://programmer.97things.oreilly.com/wiki/index.php/Encapsulate_Behavior,_not_Just_State
You can avoid getter and setter at places by using _classname__attributename because that's the changed new name once you declare private to any attribute.
So if Item is the class with a private attribute declared as __price
then instead of item.getPrice() you can write _Item__price.
It will work fine.
I had a discussion at work regarding "Inheritance in domain model is complicating developers life". I'm an OO programmer so I started to look for arguments that having inheritance in domain model will ease the developer life actually instead of having switches all over the place.
What I would like to see is this :
class Animal {
}
class Cat : Animal {
}
class Dog : Animal {
}
What the other colleague is saying is :
public enum AnimalType {
Unknown,
Cat,
Dog
}
public class Animal {
public AnimalType Type { get; set; }
}
How do I convince him (links are WELCOME ) that a class hierarchy would be better than having a enum property for this kind of situations?
Thanks!
Here is how I reason about it:
Only use inheritance if the role/type will never change.
e.g.
using inheritance for things like:
Fireman <- Employee <- Person is wrong.
as soon as Freddy the fireman changes job or becomes unemployed, you have to kill him and recreate a new object of the new type with all of the old relations attached to it.
So the naive solution to the above problem would be to give a JobTitle enum property to the person class.
This can be enough in some scenarios, e.g. if you don't need very complex behaviors associated with the role/type.
The more correct way would be to give the person class a list of roles.
Each role represents e.g an employment with a time span.
e.g.
freddy.Roles.Add(new Employement( employmentDate, jobTitle ));
or if that is overkill:
freddy.CurrentEmployment = new Employement( employmentDate, jobTitle );
This way , Freddy can become a developer w/o we having to kill him first.
However, all my ramblings still haven't answered if you should use an enum or type hierarchy for the jobtitle.
In pure in mem OO I'd say that it's more correct to use inheritance for the jobtitles here.
But if you are doing O/R mapping you might end up with a bit overcomplex data model behind the scenes if the mapper tries to map each sub type to a new table.
So in such cases, I often go for the enum approach if there is no real/complex behavior associated with the types.
I can live with a "if type == JobTitles.Fireman ..." if the usage is limited and it makes things easer or less complex.
e.g. the Entity Framework 4 designer for .NET can only map each sub type to a new table. and you might get an ugly model or alot of joins when you query your database w/o any real benefit.
However I do use inheritance if the type/role is static.
e.g. for Products.
you might have CD <- Product and Book <- Product.
Inheritance wins here because in this case you most likely have different state associated with the types.
CD might have a number of tracks property while a book might have number of pages property.
So in short, it depends ;-)
Also, at the end of the day you will most likely end up with a lot of switch statements either way.
Let's say you want to edit a "Product" , even if you use inheritance, you will probably have code like this:
if (product is Book)
Response.Redicted("~/EditBook.aspx?id" + product.id);
Because encoding the edit book url in the entity class would be plain ugly since it would force your business entites to know about your site structure etc.
Having an enum is like throwing a party for all those Open/Closed Principle is for suckers people.
It invites you to check if an animal is of a certain type and then apply custom logic for each type. And that can render horrible code, which makes it hard to continue building on your system.
Why?
Doing "if this type, do this, else do that" prevents good code.
Any time you introduce a new type, all those ifs get invalid if the new type is not handled. In larger systems, it's hard to find all those ifs, which will lead to bugs eventually.
A much better approach is to use small, well-defined feature interfaces (Interface segregation principle).
Then you will only have an if but no 'else' since all concretes can implement a specific feature.
Compare
if (animal is ICanFly flyer)
flyer.Sail();
to
// A bird and a fly are fundamentally different implementations
// but both can fly.
if (animal is Bird b)
b.Sail();
else if (animal is Fly f)
b.Sail();
See? the former one needs to be checked once while the latter has to be checked for every animal that can fly.
Enums are good when:
The set of values is fixed and never or very rarely changes.
You want to be able to represent a union of values (i.e. combining flags).
You don't need to attach other state to each value. (Java doesn't have this limitation.)
If you could solve your problem with a number, an enum is likely a good fit and more type safe. If you need any more flexibility than the above, then enums are likely not the right answer. Using polymorphic classes, you can:
Statically ensure that all type-specific behavior is handled. For example, if you need all animals to be able to Bark(), making Animal classes with an abstract Bark() method will let the compiler check for you that each subclass implements it. If you use an enum and a big switch, it won't ensure that you've handled every case.
You can add new cases (types of animals in your example). This can be done across source files, and even across package boundaries. With an enum, once you've declared it, it's frozen. Open-ended extension is one of the primary strengths of OOP.
It's important to note that your colleague's example is not in direct opposition to yours. If he wants an animal's type to be an exposed property (which is useful for some things), you can still do that without using an enum, using the type object pattern:
public abstract class AnimalType {
public static AnimalType Unknown { get; private set; }
public static AnimalType Cat { get; private set; }
public static AnimalType Dog { get; private set; }
static AnimalType() {
Unknown = new AnimalType("Unknown");
Cat = new AnimalType("Cat");
Dog = new AnimalType("Dog");
}
}
public class Animal {
public AnimalType Type { get; set; }
}
This gives you the convenience of an enum: you can do AnimalType.Cat and you can get the type of an animal. But it also gives you the flexibility of classes: you can add fields to AnimalType to store additional data with each type, add virtual methods, etc. More importantly, you can define new animal types by just creating new instances of AnimalType.
I'd urge you to reconsider: in an anemic domain model (per the comments above), cats don't behave differently than dogs, so there's no polymorphism. An animal's type really is just an attribute. It's hard to see what inheritance buys you there.
Most importantly OOPS means modeling reality. Inheritance gives you the opportunity to say Cat is an animal. Animal should not know if its a cat now shout it and then decide that it is suppose to Meow and not Bark, Encapsulation gets defeated there. Less code as now you do not have to do If else as you said.
Both solutions are right.
You should look which techniques applies better to you problem.
If your program uses few different objects, and doesn't add new classes, its better to stay with enumerations.
But if you program uses a lot of different objects (different classes), and may add new classes, in the future, better try the inheritance way.
I know this sort of question has been asked before, but I still feel that the answer is too ambiguous for me (and, by extension, some/most beginners) to grasp.
I have been trying to teach myself broader concepts of programming than procedural and basic OOP. I understand the concrete concepts of OOP (you make a class that has data (members) and functions (methods) and then instantiate that class at run time to actually do stuff, that kind of thing).
I think I have a handle on what a class is (sort of a design blueprint for an instance to be created in its likeness at compile time). But if that's the case, what is an object? I also know that in prototype based languages, this can muck things up even more, but perhaps this is why there needs to be a clear distinction between object and instance in my mind.
Beyond that, I struggle with the concepts of "object" and "instance". A lot of resources that I read (including answers at SO) say that they are largely the same and that the difference is in semantics. Other people say that there is a true conceptual difference between the two.
Can the experts here at SO help a beginner have that "aha" moment to move forward in the world of OOP?
Note: this isn't homework, I don't go to school - however, I think it would help people that are looking for homework help.
A blueprint for a house design is like a class description. All the houses built from that blueprint are objects of that class. A given house is an instance.
The truth is that object oriented programming often creates confusion by creating a disconnect between the philosophical side of development and the actual mechanical workings of the computer. I'll try to contrast the two for you:
The basic concept of OOP is this: Class >> Object >> Instance.
The class = the blue print.
The Object is an actual thing that is built based on the 'blue print' (like the house).
An instance is a virtual copy (but not a real copy) of the object.
The more technical explanation of an 'instance' is that it is a 'memory reference' or a reference variable. This means that an 'instance' is a variable in memory that only has a memory address of an object in it. The object it addresses is the same object the instance is said to be 'an instance of'. If you have many instances of an object, you really just have many variables in difference places in your memory that all have the same exact memory address in it - which are all the address of the same exact object. You can't ever 'change' an instance, although it looks like you can in your code. What you really do when you 'change' an instance is you change the original object directly. Electronically, the processor goes through one extra place in memory (the reference variable/instance) before it changes the data of the original object.
The process is: processor >> memory location of instance >> memory location of original object.
Note that it doesn't matter which instance you use - the end result will always be the same. ALL the instances will continue to maintain the same exact information in their memory locations - the object's memory address - and only the object will change.
The relationship between class and object is a bit more confusing, although philosophically its the easiest to understand (blue print >> house). If the object is actual data that is held somewhere in memory, what is 'class'? It turns out that mechanically the object is an exact copy of the class. So the class is just another variable somewhere else in memory that holds the same exact information that the object does. Note the difference between the relationships:
Object is a copy of the class.
Instance is a variable that holds the memory address of the object.
You can also have multiple objects of the same class and then multiple instances of each of those objects. In these cases, each object's set of instances are equivalent in value, but the instances between objects are not. For example:
Let Class A
From Class A let Object1, Object2, and Object3.
//Object1 has the same exact value as object2 and object3, but are in different places in memory.
from Object1>> let obj1_Instance1, obj1_Instace2 , obj1_Instance3
//all of these instances are also equivalent in value and in different places in memory. Their values = Object1.MemoryAddress.
etc.
Things get messier when you start introducing types. Here's an example using types from c#:
//assume class Person exists
Person john = new Person();
Actually, this code is easier to analyze if you break it down into two parts:
Person john;
john = new Person();
In technical speak, the first line 'declares a variable of type Person. But what does that mean?? The general explanation is that I now have an empty variable that can only hold a Person object. But wait a minute - its an empty variable! There is nothing in that variables memory location. It turns out that 'types' are mechanically meaningless. Types were originally invented as a way to manage data and nothing else. Even when you declare primitive types such as int, str, chr (w/o initializing it), nothing happens within the computer. This weird syntactical aspect of programming is part of where people get the idea that classes are the blueprint of objects. OOP's have gotten even more confusing with types with delegate types, event handlers, etc. I would try not focus on them too much and just remember that they are all a misnomer. Nothing changes with the variable until its either becomes an object or is set to a memory address of an object.
The second line is also a bit confusing because it does two things at once:
The right side "new Person()" is evaluated first. It creates a new copy of the Person class - that is, it creates a new object.
The left side "john =", is then evaluated after that. It turns john into a reference variable giving it the memory address of the object that was just created on the right side of the same line.
If you want to become a good developer, its important to understand that no computer environment ever works based on philosophic ideals. Computers aren't even that logical - they're really just a big collection of wires that are glued together using basic boolean circuits (mostly NAND and OR).
The word Class comes from Classification (A Category into which something is put), Now we have all heard that a Class is like a Blueprint,but what does this exactly mean ? It means that the Class holds a Description of a particular Category ,(I would like to show the difference between Class , Object and Instance with example using Java and I would request the readers to visualise it like a Story while reading it , and if you are not familiar with java doesn't matter) So let us start with make a Category called HumanBeing , so the Java program will expressed it as follows
class HumanBeing{
/*We will slowly build this category*/
}
Now what attributes does a HumanBeing have in general Name,Age,Height,Weight for now let us limit our self to these four attributes, let us add it to our Category
class HumanBeing{
private String Name;
private int Age;
private float Height;
private float Weight;
/*We still need to add methods*/
}
Now every category has a behaviour for example category Dog has a behaviour to bark,fetch,roll etc... , Similarly our category HumanBeing can also have certain behaviour,for example when we ask our HumanBeing what is your name/age/weight/height? It should give us its name/age/weight/height, so in java we do it as follows
class HumanBeing{
private String Name;
private int Age;
private float Height;
private float Weight;
public HumanBeing(String Name,int Age,float Height,float Weight){
this.Name = Name;
this.Age = Age;
this.Height = Height;
this.Weight = Weight;
}
public String getName(){
return this.Name;
}
public int getAge(){
return this.age;
}
public float getHeight(){
return this.Height;
}
public float getWeight(){
return this.Weight;
}
}
Now we have added behaviour to our category HumanBeing,so we can ask for its name ,age ,height ,weight but whom will you ask these details from , because class HumanBeing is just a category , it is a blueprint for example an Architect makes a blueprint on a paper of the building he wants to build , now we cannot go on live in the blueprint(its description of the building) we can only live in the building once it is built
So here we need to make a humanbeing from our category which we have described above , so how do we do that in Java
class Birth{
public static void main(String [] args){
HumanBeing firstHuman = new HumanBeing("Adam",25,6.2,90);
}
}
Now in the above example we have created our first human being with name age height weight , so what exactly is happening in the above code? . We are Instantiating our category HumanBeing i.e An Object of our class is created
Note : Object and Instance are not Synonyms In some cases it seems like Object and Instance are Synonyms but they are not, I will give both cases
Case 1: Object and Instance seems to be Synonyms
Let me elaborate a bit , when we say HumanBeing firstHuman = new HumanBeing("Adam",25,6.2,90); An Object of our category is created on the heap memory and some address is allocated to it , and firstHuman holds a reference to that address, now this Object is An Object of HumanBeing and also An Instance of HumanBeing.
Here it seems like Objects and Instance are Synonyms,I will repeat myself they are not synonyms
Let Us Resume our Story , we have created our firstHuman , now we can ask his name,age,height,weight , this is how we do it in Java
class Birth{
public static void main(String [] args){
HumanBeing firstHuman = new HumanBeing("Adam",25,6.2,90);
System.out.println(firstHuman.getName());
System.out.println(firstHuman.getAge());
...
...
}
}
so we have first human being and lets move feather by give our first human being some qualification ,let's make him a Doctor , so we need a category called Doctor and give our Doctor some behaviour ,so in java we do as follows
class Doctor extends HumanBeing{
public Doctor(String Name,int Age,float Height,float Weight){
super(Name,Age,Height,Weight);
}
public void doOperation(){
/* Do some Operation*/
}
public void doConsultation(){
/* Do so Consultation*/
}
}
Here we have used the concept of Inheritance which is bringing some reusability in the code , Every Doctor will always be a HumanBeing first , so A Doctor will have Name,Age,Weight,Height which will be Inherited from HumanBeing instead of writing it again , note that we have just written a description of a doctor we have not yet created one , so let us create a Doctor in our class Birth
class Birth{
public static void main(String [] args){
Doctor firstDoctor = new Doctor("Strange",40,6,80);
.......
.......
/*Assume some method calls , use of behaviour*/
.......
.......
}
}
Case 2: Object and Instance are not Synonyms
In the above code we can visualise that we are Instantiating our category Doctor and bringing it to life i.e we are simply creating an Object of the category Doctor , As we already know Object are created on Heap Memory and firstDoctor holds a reference to that Object on the heap ;
This particular Object firstDoctor is as follows (please note firstDoctor holds a reference to the object , it is not the object itself)
firstDoctor is An Object of class Doctor And An Instance of A class Doctor
firstDoctor is Not An Object of class HumanBeing But An Instance of class HumanBeing
So a particular Object can be an instance to a particular class but it need not be an object of that given class
Conclusion:
An Object is said to be an Instance of a particular Category if it satisfies all the characteristic of that particular Category
Real world example will be as follows , we are first born as Humans so image us as Object of Human , now when we grow up we take up responsibilities and learn new skills and play different roles in life example Son, brother, a daughter, father ,mother now What are we actually?We can say that we are Objects of Human But Instances of Brother,daughter,...,etc
I hope this helps
Thank You
Objects are things in memory while instances are things that reference to them. In the above pic:
std(instance) -> Student Object (right)
std1(instance) -> Student Object (left)
std2(instance) -> Student Object (left)
std3(instance) -> no object (null)
An object is an instance of a class (for class based languages).
I think this is the simplest explanation I can come up with.
A class defines an object. You can go even further in many languages and say an interface defines common attributes and methods between objects.
An object is something that can represent something in the real world. When you want the object to actually represent something in the real world that object must be instantiated. Instantiation means you must define the characteristics (attributes) of this specific object, usually through a constructor.
Once you have defined these characteristics you now have an instance of an object.
Hope this clears things up.
"A class describes a set of objects called its instances." - The Xerox learning Research Group, "The Smalltalk-80 System", Byte Magazine Volume 06 Number 08, p39, 1981.
What is an Object ?
An object is an instance of a class. Object can best be understood by finding real world examples around you. You desk, your laptop, your car all are good real world examples of an object.
Real world object share two characteristics, they all have state and behaviour. Humans are also a good example of an object, We humans have state/attributes - name, height, weight and behavior - walk, run, talk, sleep, code :P.
What is a Class ?
A class is a blueprint or a template that describes the details of an object. These details are viz
name
attributes/state
operations/methods
class Car
{
int speed = 0;
int gear = 1;
void changeGear(int newGear)
{
gear = newGear;
}
void speedUp(int increment)
{
speed = speed + increment;
}
void applyBrakes(int decrement)
{
speed = speed - decrement;
}
}
Consider the above example, the fields speed and gear will represent the state of the object, and methods changeGear, speedUp and applyBrakes define the behaviour of the Car object with the outside world.
References:
What is an Object ?
What is a Class ?
I think that it is important to point out that there are generally two things. The blueprint and the copies. People tend to name these different things; classes, objects, instances are just some of the names that people use for them. The important thing is that there is the blueprint and copies of it - regardless of the names for them. If you already have the understanding for these two, just avoid the other things that are confusing you.
Lets compare apples to apples. We all know what an apple is. What it looks like. What it tastes like. That is a class. It is the definition of a thing. It is what we know about a thing.
Now go find an apple. That is an instance. We can see it. We can taste it. We can do things with it. It is what we have.
Class = What we know about something. A definition.
Object/Instance = Something that fits that definition that we have and can do things with.
In some cases, the term "object" may be used to describe an instance, but in other cases it's used to describe a reference to an instance. The term "instance" only refers to the actual instance.
For example, a List may be described as a collection of objects, but what it actually holds are references to object instances.
I have always liked the idea that equals the definition of a class as that of an "Abstract Data Type". That is, when you defined a class you're are defining a new type of "something", his data type representation, in terms of primitives and other "somethings", and his behavior in terms of functions and/or methods. (Sorry for the generality and formalism)
Whenever you defined a class you open a new possibility for defining certain entities with its properties and behavior, when you instantiate and/or create a particular object out of it you're actually materializing that possibility.
Sometimes the terms object and instances are interchangeable. Some OOP purists will maintain that everything is an object, I will not complain, but in the real OOP world, we developers use two concepts:
Class: Abstract Data Type sample from which you can derive other ADT and create objects.
Objects: Also called instances, represents particular examples of the data structures and functions represented by a given Abstract Data Type.
Object Oriented Programming is a system metaphor that helps you organize the knowledge your program needs to handle, in a way that will make it easier for you to develop your program. When you choose to program using OOP you pick up your OOP-Googles, and you decide that you will see the problem of the real world as many objects collaborating between themselves, by sending messages. Instead of seeing a Guy driving a Car you see a Guy sending a message to the car indicating what he wants the car to do. The car is a big object, and will respond to that message by sending a message to it's engine or it's wheel to be able to respond properly to what the Driver told him to do in the message, etc...
After you've created your system metaphor, and you are seeing all the reality as objects sending messages, you decide to put all the things your are seeing that are relevant to your problem domain in the PC. There you notice that there are a lot of Guys driving different cards, and it's senseless to program the behavior of each one of them separately because they all behave in the same way... So you can say two things:
All those guys behave in the same way, so I'll create a class called
Driver that will specify who all the Drivers in the world behave,
because they all behave in the same way. (And your are using class based OOP)
Or your could say Hey! The second Driver behaves in the same way as the first Driver, except he likes going a little faster. And the third Driver behaves in the same way as the first Driver, except he likes zigzagging when he drives. (And you use prototype based OOP).
Then you start putting in the computer the information of how all the Drivers behave (or how the first driver behave, and how the second and third differ from that one), and after a while you have your program, and you use the code to create three drivers that are the model you are using inside that PC to refeer to the drivers you saw in the real world. Those 3 drivers that you created inside the PC are instances of either the prototype ( actually the first one is the prototype, the first one might be the prototype himself depending on how you model things) or the class that you created.
The difference between instance and object is that object is the metaphor you use in the real world. You choose to see the guy and the car as objects (It would be incorrect to say that you see them as instances) collaborating between themselves. And then you use it as inspiration to create your code. The instance only exists in your program, after you've created the prototype or the class. The "objects" exist outside the PC because its the mapping you use to unite the real world with the program. It unites the Guy with the instance of Driver you created in the PC. So object and instance are extremely related, but they are not exactly the same (an instance is a "leg" of an object in the program, and the other "leg" is in the real world).
I guess the best answer has already been given away.
Classes are blueprints, and objects are buildings or examples of that blueprint did the trick for me as well.
Sometimes, I'd like to think that classes are templates (like in MS Word), while objects are the documents that use the template.
Extending one of the earlier given examples in this thread...
Consider a scenario - There is a requirement that 5 houses need to be built in a neighbourhood for residential purposes. All 5 houses share a common construction architecture.
The construction architecture is a class.
House is an object.
Each house with people staying in it is an instance.