-
Of course you can't return a private object. That's the whole poing of OO! You can't just expose your private parts to the world! It's illegal! ;)
Seriously, that breaks encapsulation. There is no reason to return private members/expose them to the rest of the program. This defeats the entire purpose of OO design.
Quzah.
-
class Date
{
// insert usual datestuff here
public:
const char* AsText() const;
void Change( int, int, int );
};
class Person
{
private:
Date Birthdate;
public:
const Date& GetBirthdate() const
{ return Birthdate; }
void SetBirthdate( const Date& d )
{ Birthdate = d; }
};
int main()
{
Person p;
const Person cp;
Date d;
printf( p.GetBirthdate().AsString() ); // perfectly legal
p.GetBirthdate().Change(1,1,2001); // compiler error
d = cp.GetBirthdate(); // legal
cp.SetBirthdate( d ); // illegal, calling non-const function on const object
return 0;
}
This was what I'm talking about. Do this in Java. I don't think
it breaks data encapsulation in any way, it's a perfect little class.
-
Code:
class Date
{
// insert usual datestuff here
public:
const char* AsText() const;
void Change( int, int, int );
};
class Person
{
private:
Date Birthdate;
public:
const Date& GetBirthdate() const
{ return Birthdate; }
void SetBirthdate( const Date& d )
{ Birthdate = d; }
};
There is a slight problem with your code. Since this is a birthday, you don't want it changing. Face it, people's birthday's never change. As such:
Code:
class Date
{ private int d,m,yr;
public void Date( int day, int month, int year )
{ d = day; m = month; y = year; }
}
class BirthDate extends Date
{ public Date GetBirthDate( )
{ return new Date( this.d, this.m, this.y );
}
public void ShowBirthDate( )
{ System.out.println( "" + this.d + "/" + this.m + "/" + this.y );
}
}
class Person
{ private BirthDate b;
//more personal information
public Person( int day, int month, int year )
{ b = new BirthDate( day, month, year );
}
public ShowBirthday( )
{ b.ShowBirthDate( ); }
}
class MyProggie
{ public static void main( String [] args )
{ Person p = new Person( 4, 11, 2001 );
p.ShowBirthDay( );
}
}
That is how the class should be designed. More like that anyway. Yours was poor class design, in that, you are extracting information from the class in a way you shouldn't. A class should be self contained. Anything that you need from the class, it should be able to provide you with access functions.
Yes, it is more work, more lines of code, and takes longer to write;
but, if you want your classes working the way they should, then that (above) is how you'd go about it.
Granted, I just threw that together, so there are probably ways it could be done better. (For example, I should have made the functions return a string, rather than have called println inside it. I was just hacking this together real quick, thus the result.)
Additionally, my Date class could have been done better. For example, I could have used a 'final' setDate class in Birthday, to prevent the date from being changed, something along that line.
Quzah.
-
>There is a slight problem with your code. Since this is a birthday, you don't want it changing.
Jesus... than rename it to DateOfLastPayment. The problem still stands as I described it.
Do you think giving read access to your privates is wrong ?
If so, have fun programming, you will have a hard time.
class a;
class b
{
private :
a A;
public:
const a& GetA();
};
class c
{
public:
int CalculateResultForAnyA( a SomeA );
};
Get a result from the private of b:
int r = aC.CalculateResultForAnyA( aB.GetA() );
However you do this in Java, you cannot guarantee
that the calculating function will not change the a-object
it gets. The best you can do is create a copy of it, so
changing it has no effect.
-
quzah,
External objects should not be able to change an object's internal "private" attributes, but it is perfectly acceptable to pass these private and protected values to external objects who request them. That's what a get() method is for, remember? nvoigt's right; it would be nearly impossible to program using objects that do not interact...
>>However you do this in Java, you cannot guarantee
that the calculating function will not change the a-object
it gets. The best you can do is create a copy of it, so
changing it has no effect.<<
nvoigt, i have no experience with java so this might be obviouis, but is there no const keyword? Therefore the CaculateResultForAnyA() method cannot modify the parameters passed to it. basically can you give an example of what you're explaning here. I'm just curious...
-
>i have no experience with java so this might be obviouis, but is there no const keyword?
*g* You mentioned the problem right head on ;)
Passing is by reference only for objects, and a
const keyword does not exist... now go and build
a get-function for a non-primitive...
-
Actually, while they do not call it 'const', Java has 'final', which is the same thing.
Code:
class A { //class A
private int x; //some data here
public int getX( ) { return x; }
public void setX( int y ) { x = y; }
}
class B {
private A iA; //private instance clA
public B( ) { iA = new A( ); }
public final A getA( ) { return iA; }
}
class MyApp {
public static void main( String[] args ) {
B iB = new B( );
iB.getA( ).setX( 333 );
System.out.println( "A.x is " + iB.getA( ).getX( ) );
}
}
Now then, THIS does what you say Java cannot do. Keep in mind that I've only been tinkering with Java for a few weeks. (Little of which is actual coding.) Enjoy.
Additionally, you are both missing the concept of OOD. You do not want to have random objects and methods directly accessing your date. I'll admit I haven't done a lot of OOP, so I may be off in my assessment, but I believe the general idea behind OOD is keeping your objects self-contained so that no one who doesn't belong can get their hands on your data.
Quzah.
-
I don't think 'final' will work, for objects it means the reference can't be used to reference another object like -
char* const a;
would prevent 'a' from pointing elsewhere but wouldn't prevent modification of the value stored at 'a' in C.
-
>You do not want to have random objects and methods directly accessing your date.
You don't have another chance. You have to grant interfaces to your privates, and a get-function is probably the most renowned way of granting read access to privates, which is fine. You are right saying that you don't want them to access the data for writing.
>iB.getA( ).setX( 333 );
I admitedly don't have a java compiler handy at home. A well implemented compiler should either scream and shout and wave every flag available, or silently step aside and commit sepuku when compiling this line. If it produces executable code from this line, it's crap.
And I assume it will, because the final keyword is not what you would expect from it. Easier question: Create a constant object.
Example:
Code:
class c
{
private int i;
public c() { i = 0; }
public int getI(){ return i; }
public void setI( int newi ){ i = newi; }
};
class MyApp
{
public static void main( String[] args )
{
final c C = new c();
C.setI( 555 );
return 0;
}
}
In what way is that C constant ?
You can change it any way you want.
The Reference is constant. The object is not.
-
>> iB.getA( ).setX( 333 );
>
>I admitedly don't have a java compiler handy at home. A well
> implemented compiler should either scream and shout and
> wave every flag available, or silently step aside and commit
> sepuku when compiling this line. If it produces executable code
> from this line, it's crap.
Actually, I'm using the Sun Java compiler (1.3 i believe) and it
compiles without error or warning, and executes correctly. The
reason it works is that 'setX' is a public method.
I could have also just done:
iB.iA.setX( 333 );
In either case, the end result is the same. 'iA' calls 'setX'.
In your example using 'final', this means that instance of the class is final. How that exactly works, I am not entirely sure. Perhaps you cannot do:
final c myC = new C( ); //give C an instance
myC = new C( ); //give it a new one
I believe that's what you're looking at there.
If you want an unchangable class, you declare the class as final:
final class C {
}
This means that you can't exctend that class. Thus:
class D extends C { //this is invalid
}
Anyway, going from the book I have, "Core Java 2", which is used for certification, they state that 'final' is basicly the same as 'const'. I'm at work now, and the book is at home so without going to http://java.sun.com and hunting around for it, that's the best I can do for now.
The best analogy I can guess at here (I don't know enough Java to say with100% certainty.) is that basicly, everything in Java is a pointer. This is why you have to use: 'x = new X( );' all the time.
If you try and give C a new value, once it's already been given one:
c C = new c( );
C = new c( ); //second value
It will fail. I tried:
Code:
C:\WINDOWS\Desktop>javac MyApp2.java
MyApp2.java:18: Can't assign a value to a final variable: C
C = new c( );
^
1 error
So basicly, it's like making the pointer constant, in that, you can give it a value once, and from then on, it cannot be changed.
And I believe that's how "Core Jave:Volume 1" describes it. "final" means (for instances, I suspect) that you can give it a value once, and from then on, you cannot change it. Thus, if you want your methods to be "constant", then you have to declare the method as final. If you want a data member constant, you have to declare it final.
A final method cannot be overridden either, at least I believe so.
I wish we had a Java board...
Quzah.
-
If your iB.getA( ) had returned a constant A object then you wouldn't have been able to call setX( 333 ) on it, so iB.getA( ).setX( 333 ); should be illegal. You are modifying an object that has been returned from a Get() method and this method doesn't protect it. If you wanted exclusive control of an 'A' object from within' B', and wanted to provide external read-only access to it, how would 'B' know when this 'A' is being modified?
-
> If your iB.getA( ) had returned a constant A object then you
> wouldn't have been able to call setX( 333 ) on it, so iB.getA
> ( ).setX( 333 ); should be illegal.
Hm... Yup. It would seem so. However, it compiles and runs. I
really don't have the answer to why. Let's try...
Code:
class A { //class A
private int x; //some data here
public int getX( ) { return x; }
public void setX( int y ) { x = y; }
}
class B {
private A iA; //private instance clA
public B( ) { iA = new A( ); }
public final A getA( ) { return iA; }
}
class MyApp {
public static void main( String[] args ) {
B iB = new B( );
iB.getA( ).setX( 333 );
System.out.println( "A.x is " + iB.getA( ).getX( ) );
iB.getA( ).setX( 444 );
System.out.println( "A.x is " + iB.getA( ).getX( ) );
iB.iA.setX( 555 );
System.out.println( "A.x is " + iB.getA( ).getX( ) );
}
}
MyApp.java:22: Variable iA in class B not accessible from class MyApp.
iB.iA.setX( 555 );
^
Ok, so what exactly is this saying? We cannot access 'iA' because we're in another class while doing it? Got me. I thought this'd work. Hell, it should work, IMO. Examine:
iB = public
iA = private member of iB
Since it's private, 'iB' should be able to access it, but other classes cannot. But, when we do:
iB.getA( ).setX( ... );
This works because we're returning an iA object, and having it call it's own functions. Eeh.. I need a Java board.
> You are modifying an object that has been returned from a Get()
> method and this method doesn't protect it. If you wanted
> exclusive control of an 'A' object from within' B', and wanted to
> provide external read-only access to it, how would 'B' know
> when this 'A' is being modified?
I'm not sure. My lunch is over, so I'll mull this around abit, and see what I can come up with...
Quzah.
-
http://java.sun.com/docs/books/tutor...sscontrol.html
Well I've been tinkering with this, and I'm not sure I'm liking what I find. (What I find, is that it isn't working the way I thought it should be working.)
Code:
class A {
private int x; //should be only available to this class's members
public int getX( ) { return x; } //should be available to everyone
protected void setX( int y ) { x = y; } //only this and subclasses
}
class B {
public A pubA = new A( ); //everyone can play with this
private A priA = new A( ); //only B's members?
protected A proA = new A( ); //only this and B's subclasses
public A getpubA( ) { return pubA; }
private A getpriA( ) { return priA; }
protected A getproA( ) { return proA; }
}
class MiApp {
public static void main( String [] args ) {
B iB = new B( );
// All is legal. We're strictly public here. Free for all.
iB.pubA.setX( 1 );
System.out.println( "iB.pubA.getX( ) == " + iB.pubA.getX( ) );
//error, iB does not have access to 'priA' in class 'MiApp'.
//error for these next two lines.
iB.priA.setX( 2 );
System.out.println( "iB.priA.getX( ) == " + iB.priA.getX( ) );
//This leads me to the following conclusion:
// 'MiApp' is the one that the compiler believes is accessing
// the inner workings of 'iB'. In other words, just because
// 'MiApp' __HAS A__ 'iB', does not mean that it can access
// the contents of 'iB'.
//This is also legal, because with 'protected', we extend access
//to those classes that 'have a' instance of said class. Actually,
//I believe it works because we're in the same 'package', (ie: in
//this case, the same file. An external file that had a 'B'
//instance would fail here? Haven't tried it.
iB.proA.setX( 3 );
System.out.println( "iB.proA.getX( ) == " + iB.proA.getX( ) );
}
}
How does that relate with us returning data and the 'final' keyword? I'll get to work on that now that I __think__ I understand how the access works. :)
Quzah.
-
<< Ok, so what exactly is this saying? We cannot access 'iA' because we're in another class while doing it? Got me. I thought this'd work. Hell, it should work, IMO.>>
i've been following, lurking in the shadows. Remember that i have no knowledge of java...
i would guess that this is similar to C++. You can't get to object iA or any of its methods (setX) because it is a private object. You would have to define methods in class B to change the values in iA or define iB as public. iB's interal operations can access iA, but external classes (ie MyApp) have to get to iA through the defined interface: (question marks denote confusion over java syntax ;) )
Code:
class B {
private A iA; //private instance clA
public B( ) { iA = new A( ); }
public final A getA( ) { return iA; }
public void(?) setA (A obj) { iA = obj; } // assuming operator is overloaded
public void(?) setA (int x) { iA.setX (x); ]
}
this confuses me too:
iB.getA().setX(555). So, in java all objects returned from get() methods are returned by reference? That's crazy. Consider the following C++ example:
Code:
class A {
public:
A () { x = 0; }
void setX (int a) { x = a; }
int getX () { return x; }
private:
int x;
};
class B {
public:
B () : iA () {}
A getAvalue() const { return iA; }
A& getAref() { return iA; }
private:
A iA;
};
int main ()
{
B iB;
iB.getAvalue().setX(2); // value of iA.x is preserved
cout << iB.getAValue().getX() << endl; // 'see
iB.getAref().setX(3); // returning dangling ref allows corruption of data
cout << iB.getAvalue().getX() << endl; // 'see
return 0;
}
i'm, very surprised that java doesn't allow for the same protection. That can't be true. i thought one of the main ideas behind the super high level languages was to protect the programmer from mistakes like this? i must be missing something....
-
> public void(?) setA (A obj) { iA = obj; } // assuming...
Yep, this is correct. Or would be rather. This, in Java, is just like this in C++:
Code:
class A {
public:
A( ) { obj = new Object( ); } //can't remember if you use () here
void setObj( Obj o ) { if( obj ) delete( obj ); obj = o; }
private:
Object *ob;
};
As far as passing by reference, pretty much. However, I'd be really really surprised if there wasn't a way to prevent changes when you didn't want them. (ie: const/final) I just am not sure how yet :P
Quzah.