How to implement RealNumber and ComplexNumber inheritance?
Clash Royale CLAN TAG#URR8PPP
Hopefully not too academic...
Let's say I need real and complex numbers in my SW library.
Based on is-a (or here) relationship, real number is a complex number, where b in imaginary part of complex number is simply 0.
On the other hand, my implementation would be, that child extends parent, so in parent RealNumber I'd have real part and child ComplexNumber would add imaginary art.
Also there is an opinion, that inheritance is evil.
I recall like yesterday, when I was learning OOP at university, my professor said, this is not a good example of inheritance as absolute value of those two is calculated differently (but for that we have method overloading/polymorfism, right?)...
My experience is, that we often use inheritance to solve DRY, as a result we have often artificial abstract classes in hierarchy (we often have problem to find names for as they do not represent objects from a real world).
design inheritance
|
show 11 more comments
Hopefully not too academic...
Let's say I need real and complex numbers in my SW library.
Based on is-a (or here) relationship, real number is a complex number, where b in imaginary part of complex number is simply 0.
On the other hand, my implementation would be, that child extends parent, so in parent RealNumber I'd have real part and child ComplexNumber would add imaginary art.
Also there is an opinion, that inheritance is evil.
I recall like yesterday, when I was learning OOP at university, my professor said, this is not a good example of inheritance as absolute value of those two is calculated differently (but for that we have method overloading/polymorfism, right?)...
My experience is, that we often use inheritance to solve DRY, as a result we have often artificial abstract classes in hierarchy (we often have problem to find names for as they do not represent objects from a real world).
design inheritance
7
this looks like covered in prior question: Should rectangle inherit from square?
– gnat
Jan 9 at 13:37
1
@gnat Oh man, that was another example I wanted to use... Thanks!
– Betlista
Jan 9 at 14:14
7
... Note that the sentence "real number is a complex number" in the mathematical sense is only valid for immutable numbers, so if you use immutable objects, you can avoid the LSP violation (same holds also for squares and rectangles, see this SO answer).
– Doc Brown
Jan 9 at 15:20
5
... Note further the absolute value calculation for complex numbers works also for real numbers, so I am not sure what your professor meant. If you implement an "Abs()" method correctly in an immutable complex number and derive a "real" from it, the Abs() method will still deliver correct results.
– Doc Brown
Jan 9 at 15:23
3
Possible duplicate of Should rectangle inherit from square?
– BobDalgleish
Jan 9 at 17:21
|
show 11 more comments
Hopefully not too academic...
Let's say I need real and complex numbers in my SW library.
Based on is-a (or here) relationship, real number is a complex number, where b in imaginary part of complex number is simply 0.
On the other hand, my implementation would be, that child extends parent, so in parent RealNumber I'd have real part and child ComplexNumber would add imaginary art.
Also there is an opinion, that inheritance is evil.
I recall like yesterday, when I was learning OOP at university, my professor said, this is not a good example of inheritance as absolute value of those two is calculated differently (but for that we have method overloading/polymorfism, right?)...
My experience is, that we often use inheritance to solve DRY, as a result we have often artificial abstract classes in hierarchy (we often have problem to find names for as they do not represent objects from a real world).
design inheritance
Hopefully not too academic...
Let's say I need real and complex numbers in my SW library.
Based on is-a (or here) relationship, real number is a complex number, where b in imaginary part of complex number is simply 0.
On the other hand, my implementation would be, that child extends parent, so in parent RealNumber I'd have real part and child ComplexNumber would add imaginary art.
Also there is an opinion, that inheritance is evil.
I recall like yesterday, when I was learning OOP at university, my professor said, this is not a good example of inheritance as absolute value of those two is calculated differently (but for that we have method overloading/polymorfism, right?)...
My experience is, that we often use inheritance to solve DRY, as a result we have often artificial abstract classes in hierarchy (we often have problem to find names for as they do not represent objects from a real world).
design inheritance
design inheritance
edited Jan 9 at 20:14
mrflash818
1073
1073
asked Jan 9 at 13:33
BetlistaBetlista
21937
21937
7
this looks like covered in prior question: Should rectangle inherit from square?
– gnat
Jan 9 at 13:37
1
@gnat Oh man, that was another example I wanted to use... Thanks!
– Betlista
Jan 9 at 14:14
7
... Note that the sentence "real number is a complex number" in the mathematical sense is only valid for immutable numbers, so if you use immutable objects, you can avoid the LSP violation (same holds also for squares and rectangles, see this SO answer).
– Doc Brown
Jan 9 at 15:20
5
... Note further the absolute value calculation for complex numbers works also for real numbers, so I am not sure what your professor meant. If you implement an "Abs()" method correctly in an immutable complex number and derive a "real" from it, the Abs() method will still deliver correct results.
– Doc Brown
Jan 9 at 15:23
3
Possible duplicate of Should rectangle inherit from square?
– BobDalgleish
Jan 9 at 17:21
|
show 11 more comments
7
this looks like covered in prior question: Should rectangle inherit from square?
– gnat
Jan 9 at 13:37
1
@gnat Oh man, that was another example I wanted to use... Thanks!
– Betlista
Jan 9 at 14:14
7
... Note that the sentence "real number is a complex number" in the mathematical sense is only valid for immutable numbers, so if you use immutable objects, you can avoid the LSP violation (same holds also for squares and rectangles, see this SO answer).
– Doc Brown
Jan 9 at 15:20
5
... Note further the absolute value calculation for complex numbers works also for real numbers, so I am not sure what your professor meant. If you implement an "Abs()" method correctly in an immutable complex number and derive a "real" from it, the Abs() method will still deliver correct results.
– Doc Brown
Jan 9 at 15:23
3
Possible duplicate of Should rectangle inherit from square?
– BobDalgleish
Jan 9 at 17:21
7
7
this looks like covered in prior question: Should rectangle inherit from square?
– gnat
Jan 9 at 13:37
this looks like covered in prior question: Should rectangle inherit from square?
– gnat
Jan 9 at 13:37
1
1
@gnat Oh man, that was another example I wanted to use... Thanks!
– Betlista
Jan 9 at 14:14
@gnat Oh man, that was another example I wanted to use... Thanks!
– Betlista
Jan 9 at 14:14
7
7
... Note that the sentence "real number is a complex number" in the mathematical sense is only valid for immutable numbers, so if you use immutable objects, you can avoid the LSP violation (same holds also for squares and rectangles, see this SO answer).
– Doc Brown
Jan 9 at 15:20
... Note that the sentence "real number is a complex number" in the mathematical sense is only valid for immutable numbers, so if you use immutable objects, you can avoid the LSP violation (same holds also for squares and rectangles, see this SO answer).
– Doc Brown
Jan 9 at 15:20
5
5
... Note further the absolute value calculation for complex numbers works also for real numbers, so I am not sure what your professor meant. If you implement an "Abs()" method correctly in an immutable complex number and derive a "real" from it, the Abs() method will still deliver correct results.
– Doc Brown
Jan 9 at 15:23
... Note further the absolute value calculation for complex numbers works also for real numbers, so I am not sure what your professor meant. If you implement an "Abs()" method correctly in an immutable complex number and derive a "real" from it, the Abs() method will still deliver correct results.
– Doc Brown
Jan 9 at 15:23
3
3
Possible duplicate of Should rectangle inherit from square?
– BobDalgleish
Jan 9 at 17:21
Possible duplicate of Should rectangle inherit from square?
– BobDalgleish
Jan 9 at 17:21
|
show 11 more comments
5 Answers
5
active
oldest
votes
Even if in a mathematical sense, a real number is a complex number, it is not a good idea to derive real from complex. It violates the Liskov Substitution Principle saying (among other things) that a derived class should not hide properties of a base class.
In this case a real number would have to hide the imaginary part of the complex number. It is clear that it makes no sense to store a hidden floating point number (imaginary part) if you only need the real part.
This is basically the same issue as the rectangle/square example mentioned in a comment.
2
Today I saw this "Liskow Substitution Principle" several times, I'll have to read more about it, because I do not know that.
– Betlista
Jan 9 at 14:17
7
It is perfectly fine to report the imaginary part of a real number as zero, e.g. through a read-only method. But it makes no sense to implement a real as a complex number where the imaginary part is set to zero. This is exactly a case where inheritance is misleading: while interface inheritance would arguably be fine here, implementation inheritance would result in a problematic design.
– amon
Jan 9 at 14:26
4
It makes perfect sense to have real numbers inherit from complex numbers, as long as both are immutable. And you don't mind the overhead.
– Deduplicator
Jan 9 at 19:20
@Deduplicator: Interesting point. Immutability resolves lots of issues but I am not fully convinced yet in this case. Have to think about it.
– Frank Puffer
Jan 9 at 20:21
add a comment |
not a good example of inheritance as absolute value of those two is calculated differently
This isn't actually a compelling reason against all inheritance here, just the proposed class RealNumber
<-> class ComplexNumber
model.
You might reasonably define an interface Number
, which both RealNumber
and ComplexNumber
would implement.
That might look like
interface Number
Number Add(Number rhs);
Number Subtract(Number rhs);
// ... etc
But then you'd want to constrain the other Number
parameters in these operations to be the same derived type as this
, which you can get close to with
interface Number<T>
Number<T> Add(Number<T> rhs);
Number<T> Subtract(Number<T> rhs);
// ... etc
Or instead you'd use a language that allowed structural polymorphism, instead of subtype polymorphism. For the specific case of numbers, you might only need the ability to overload arithmetic operators.
complex operator + (complex lhs, complex rhs);
complex operator - (complex lhs, complex rhs);
// ... etc
Number frobnicate<Number>(List<Number> foos, Number bar); // uses arithmetic operations
add a comment |
Solution: Do not have a public RealNumber
class
I would find it totally OK if ComplexNumber
had a static factory method fromDouble(double)
that would return a complex number with imaginary being zero. You can then use all the operations that you would use on a RealNumber
instance on this ComplexNumber
instance.
But I have trouble seeing why you would want/need to have a public inherited RealNumber
class. Usually inheritance is used for these reasons (out of my head, correct me if missed some)
extending the behaviour.
RealNumbers
cannot do any extra operations complex number can't do, so no point in doing this.implementing abstract behaviour with a specific implementation. Since
ComplexNumber
should not be abstract this also does not apply.code reuse. If you just use the
ComplexNumber
class you reuse 100% of the code.more specific/efficient/accurate implementation for a specific task. This could be applied here,
RealNumbers
could implement some functionalities faster. But then this subclass should be hidden behind the staticfromDouble(double)
and should not be known outside. This way it would not need to hide the imaginary part. For the outside there should only be complex numbers (which real numbers are). You could also return this private RealNumber class from any operations in the complex number class that results in a real number. (This assumes the classes are immutable as most number classes.)
It is like implementing a subclass of Integer that is called Zero and hardcode some of the operations since they are trivial for zero. You could do this, as every zero is an integer, but don't make it public, hide it behind a factory method.
I am not surprised to get some downvote, since I have no source to prove. Also if nobody else had an idea, I always suspect there might be some reason for that. But please tell me why you think it is wrong and how you would make it better.
– findusl
Jan 10 at 9:06
add a comment |
Saying that a real number is a complex number has more meaning in mathematics, especially set theory, than computer science.
In mathematics we say :
- A real number is a complex number because the set of complex numbers
includes the set of real numbers. - A rational number is a real number because the set of real numbers includes the set of rational numbers (and the set of
irrational numbers). - An integer is a rational number because the set of rational numbers includes the set of integers.
However, this does not mean you must, or even should, use inheritance when designing your library to include a RealNumber and ComplexNumber class. In Effective Java, Second Edition by Joshua Bloch; Item 16 is "Favor Composition Over Inheritance". To avoid the problems mentioned in that item, once you have your RealNumber class defined, it can be used in your ComplexNumber class:
public class ComplexNumber
private RealNumber realPart;
private RealNumber imaginaryPart;
// Implementation details are for you to write
This allows you all the power of reusing your RealNumber class to keep your code DRY while avoiding the issues identified by Joshua Bloch.
add a comment |
There are two issues here. The first is that it's common to use the same terms for the types of containers and the types of their contents, especially with primitive types like numbers. The term double
, for example, is used to describe both a double-precision floating-point value and a container in which one may be stored.
The second issue is that while is-a relationships among containers from which various types of objects can be read behave the same as the relationships among the objects themselves, those among containers into which various types of objects can be placed behave opposite those among their contents. Every cage that's known to hold an instance of Cat
will be a cage that holds an instance of Animal
, but need not be be a cage that holds an instance of SiameseCat
. On the other hand, every cage that can hold all instances of Cat
will be a cage that can hold all instances of SiameseCat
, but need not be a cage that can hold all instances of Animal
. The only kind of cage that can hold all instances of Cat
and can be guaranteed never hold anything other than an instance of Cat
, is a cage of Cat
. Any other kind of cage would either be incapable of accepting some instances of Cat
that it should accept, or would be capable of accepting things that are not instances of Cat
.
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "131"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f385185%2fhow-to-implement-realnumber-and-complexnumber-inheritance%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
Even if in a mathematical sense, a real number is a complex number, it is not a good idea to derive real from complex. It violates the Liskov Substitution Principle saying (among other things) that a derived class should not hide properties of a base class.
In this case a real number would have to hide the imaginary part of the complex number. It is clear that it makes no sense to store a hidden floating point number (imaginary part) if you only need the real part.
This is basically the same issue as the rectangle/square example mentioned in a comment.
2
Today I saw this "Liskow Substitution Principle" several times, I'll have to read more about it, because I do not know that.
– Betlista
Jan 9 at 14:17
7
It is perfectly fine to report the imaginary part of a real number as zero, e.g. through a read-only method. But it makes no sense to implement a real as a complex number where the imaginary part is set to zero. This is exactly a case where inheritance is misleading: while interface inheritance would arguably be fine here, implementation inheritance would result in a problematic design.
– amon
Jan 9 at 14:26
4
It makes perfect sense to have real numbers inherit from complex numbers, as long as both are immutable. And you don't mind the overhead.
– Deduplicator
Jan 9 at 19:20
@Deduplicator: Interesting point. Immutability resolves lots of issues but I am not fully convinced yet in this case. Have to think about it.
– Frank Puffer
Jan 9 at 20:21
add a comment |
Even if in a mathematical sense, a real number is a complex number, it is not a good idea to derive real from complex. It violates the Liskov Substitution Principle saying (among other things) that a derived class should not hide properties of a base class.
In this case a real number would have to hide the imaginary part of the complex number. It is clear that it makes no sense to store a hidden floating point number (imaginary part) if you only need the real part.
This is basically the same issue as the rectangle/square example mentioned in a comment.
2
Today I saw this "Liskow Substitution Principle" several times, I'll have to read more about it, because I do not know that.
– Betlista
Jan 9 at 14:17
7
It is perfectly fine to report the imaginary part of a real number as zero, e.g. through a read-only method. But it makes no sense to implement a real as a complex number where the imaginary part is set to zero. This is exactly a case where inheritance is misleading: while interface inheritance would arguably be fine here, implementation inheritance would result in a problematic design.
– amon
Jan 9 at 14:26
4
It makes perfect sense to have real numbers inherit from complex numbers, as long as both are immutable. And you don't mind the overhead.
– Deduplicator
Jan 9 at 19:20
@Deduplicator: Interesting point. Immutability resolves lots of issues but I am not fully convinced yet in this case. Have to think about it.
– Frank Puffer
Jan 9 at 20:21
add a comment |
Even if in a mathematical sense, a real number is a complex number, it is not a good idea to derive real from complex. It violates the Liskov Substitution Principle saying (among other things) that a derived class should not hide properties of a base class.
In this case a real number would have to hide the imaginary part of the complex number. It is clear that it makes no sense to store a hidden floating point number (imaginary part) if you only need the real part.
This is basically the same issue as the rectangle/square example mentioned in a comment.
Even if in a mathematical sense, a real number is a complex number, it is not a good idea to derive real from complex. It violates the Liskov Substitution Principle saying (among other things) that a derived class should not hide properties of a base class.
In this case a real number would have to hide the imaginary part of the complex number. It is clear that it makes no sense to store a hidden floating point number (imaginary part) if you only need the real part.
This is basically the same issue as the rectangle/square example mentioned in a comment.
edited Jan 9 at 20:13
Bob Gilmore
1033
1033
answered Jan 9 at 14:11
Frank PufferFrank Puffer
3,92451333
3,92451333
2
Today I saw this "Liskow Substitution Principle" several times, I'll have to read more about it, because I do not know that.
– Betlista
Jan 9 at 14:17
7
It is perfectly fine to report the imaginary part of a real number as zero, e.g. through a read-only method. But it makes no sense to implement a real as a complex number where the imaginary part is set to zero. This is exactly a case where inheritance is misleading: while interface inheritance would arguably be fine here, implementation inheritance would result in a problematic design.
– amon
Jan 9 at 14:26
4
It makes perfect sense to have real numbers inherit from complex numbers, as long as both are immutable. And you don't mind the overhead.
– Deduplicator
Jan 9 at 19:20
@Deduplicator: Interesting point. Immutability resolves lots of issues but I am not fully convinced yet in this case. Have to think about it.
– Frank Puffer
Jan 9 at 20:21
add a comment |
2
Today I saw this "Liskow Substitution Principle" several times, I'll have to read more about it, because I do not know that.
– Betlista
Jan 9 at 14:17
7
It is perfectly fine to report the imaginary part of a real number as zero, e.g. through a read-only method. But it makes no sense to implement a real as a complex number where the imaginary part is set to zero. This is exactly a case where inheritance is misleading: while interface inheritance would arguably be fine here, implementation inheritance would result in a problematic design.
– amon
Jan 9 at 14:26
4
It makes perfect sense to have real numbers inherit from complex numbers, as long as both are immutable. And you don't mind the overhead.
– Deduplicator
Jan 9 at 19:20
@Deduplicator: Interesting point. Immutability resolves lots of issues but I am not fully convinced yet in this case. Have to think about it.
– Frank Puffer
Jan 9 at 20:21
2
2
Today I saw this "Liskow Substitution Principle" several times, I'll have to read more about it, because I do not know that.
– Betlista
Jan 9 at 14:17
Today I saw this "Liskow Substitution Principle" several times, I'll have to read more about it, because I do not know that.
– Betlista
Jan 9 at 14:17
7
7
It is perfectly fine to report the imaginary part of a real number as zero, e.g. through a read-only method. But it makes no sense to implement a real as a complex number where the imaginary part is set to zero. This is exactly a case where inheritance is misleading: while interface inheritance would arguably be fine here, implementation inheritance would result in a problematic design.
– amon
Jan 9 at 14:26
It is perfectly fine to report the imaginary part of a real number as zero, e.g. through a read-only method. But it makes no sense to implement a real as a complex number where the imaginary part is set to zero. This is exactly a case where inheritance is misleading: while interface inheritance would arguably be fine here, implementation inheritance would result in a problematic design.
– amon
Jan 9 at 14:26
4
4
It makes perfect sense to have real numbers inherit from complex numbers, as long as both are immutable. And you don't mind the overhead.
– Deduplicator
Jan 9 at 19:20
It makes perfect sense to have real numbers inherit from complex numbers, as long as both are immutable. And you don't mind the overhead.
– Deduplicator
Jan 9 at 19:20
@Deduplicator: Interesting point. Immutability resolves lots of issues but I am not fully convinced yet in this case. Have to think about it.
– Frank Puffer
Jan 9 at 20:21
@Deduplicator: Interesting point. Immutability resolves lots of issues but I am not fully convinced yet in this case. Have to think about it.
– Frank Puffer
Jan 9 at 20:21
add a comment |
not a good example of inheritance as absolute value of those two is calculated differently
This isn't actually a compelling reason against all inheritance here, just the proposed class RealNumber
<-> class ComplexNumber
model.
You might reasonably define an interface Number
, which both RealNumber
and ComplexNumber
would implement.
That might look like
interface Number
Number Add(Number rhs);
Number Subtract(Number rhs);
// ... etc
But then you'd want to constrain the other Number
parameters in these operations to be the same derived type as this
, which you can get close to with
interface Number<T>
Number<T> Add(Number<T> rhs);
Number<T> Subtract(Number<T> rhs);
// ... etc
Or instead you'd use a language that allowed structural polymorphism, instead of subtype polymorphism. For the specific case of numbers, you might only need the ability to overload arithmetic operators.
complex operator + (complex lhs, complex rhs);
complex operator - (complex lhs, complex rhs);
// ... etc
Number frobnicate<Number>(List<Number> foos, Number bar); // uses arithmetic operations
add a comment |
not a good example of inheritance as absolute value of those two is calculated differently
This isn't actually a compelling reason against all inheritance here, just the proposed class RealNumber
<-> class ComplexNumber
model.
You might reasonably define an interface Number
, which both RealNumber
and ComplexNumber
would implement.
That might look like
interface Number
Number Add(Number rhs);
Number Subtract(Number rhs);
// ... etc
But then you'd want to constrain the other Number
parameters in these operations to be the same derived type as this
, which you can get close to with
interface Number<T>
Number<T> Add(Number<T> rhs);
Number<T> Subtract(Number<T> rhs);
// ... etc
Or instead you'd use a language that allowed structural polymorphism, instead of subtype polymorphism. For the specific case of numbers, you might only need the ability to overload arithmetic operators.
complex operator + (complex lhs, complex rhs);
complex operator - (complex lhs, complex rhs);
// ... etc
Number frobnicate<Number>(List<Number> foos, Number bar); // uses arithmetic operations
add a comment |
not a good example of inheritance as absolute value of those two is calculated differently
This isn't actually a compelling reason against all inheritance here, just the proposed class RealNumber
<-> class ComplexNumber
model.
You might reasonably define an interface Number
, which both RealNumber
and ComplexNumber
would implement.
That might look like
interface Number
Number Add(Number rhs);
Number Subtract(Number rhs);
// ... etc
But then you'd want to constrain the other Number
parameters in these operations to be the same derived type as this
, which you can get close to with
interface Number<T>
Number<T> Add(Number<T> rhs);
Number<T> Subtract(Number<T> rhs);
// ... etc
Or instead you'd use a language that allowed structural polymorphism, instead of subtype polymorphism. For the specific case of numbers, you might only need the ability to overload arithmetic operators.
complex operator + (complex lhs, complex rhs);
complex operator - (complex lhs, complex rhs);
// ... etc
Number frobnicate<Number>(List<Number> foos, Number bar); // uses arithmetic operations
not a good example of inheritance as absolute value of those two is calculated differently
This isn't actually a compelling reason against all inheritance here, just the proposed class RealNumber
<-> class ComplexNumber
model.
You might reasonably define an interface Number
, which both RealNumber
and ComplexNumber
would implement.
That might look like
interface Number
Number Add(Number rhs);
Number Subtract(Number rhs);
// ... etc
But then you'd want to constrain the other Number
parameters in these operations to be the same derived type as this
, which you can get close to with
interface Number<T>
Number<T> Add(Number<T> rhs);
Number<T> Subtract(Number<T> rhs);
// ... etc
Or instead you'd use a language that allowed structural polymorphism, instead of subtype polymorphism. For the specific case of numbers, you might only need the ability to overload arithmetic operators.
complex operator + (complex lhs, complex rhs);
complex operator - (complex lhs, complex rhs);
// ... etc
Number frobnicate<Number>(List<Number> foos, Number bar); // uses arithmetic operations
answered Jan 9 at 14:49
CalethCaleth
5,73611320
5,73611320
add a comment |
add a comment |
Solution: Do not have a public RealNumber
class
I would find it totally OK if ComplexNumber
had a static factory method fromDouble(double)
that would return a complex number with imaginary being zero. You can then use all the operations that you would use on a RealNumber
instance on this ComplexNumber
instance.
But I have trouble seeing why you would want/need to have a public inherited RealNumber
class. Usually inheritance is used for these reasons (out of my head, correct me if missed some)
extending the behaviour.
RealNumbers
cannot do any extra operations complex number can't do, so no point in doing this.implementing abstract behaviour with a specific implementation. Since
ComplexNumber
should not be abstract this also does not apply.code reuse. If you just use the
ComplexNumber
class you reuse 100% of the code.more specific/efficient/accurate implementation for a specific task. This could be applied here,
RealNumbers
could implement some functionalities faster. But then this subclass should be hidden behind the staticfromDouble(double)
and should not be known outside. This way it would not need to hide the imaginary part. For the outside there should only be complex numbers (which real numbers are). You could also return this private RealNumber class from any operations in the complex number class that results in a real number. (This assumes the classes are immutable as most number classes.)
It is like implementing a subclass of Integer that is called Zero and hardcode some of the operations since they are trivial for zero. You could do this, as every zero is an integer, but don't make it public, hide it behind a factory method.
I am not surprised to get some downvote, since I have no source to prove. Also if nobody else had an idea, I always suspect there might be some reason for that. But please tell me why you think it is wrong and how you would make it better.
– findusl
Jan 10 at 9:06
add a comment |
Solution: Do not have a public RealNumber
class
I would find it totally OK if ComplexNumber
had a static factory method fromDouble(double)
that would return a complex number with imaginary being zero. You can then use all the operations that you would use on a RealNumber
instance on this ComplexNumber
instance.
But I have trouble seeing why you would want/need to have a public inherited RealNumber
class. Usually inheritance is used for these reasons (out of my head, correct me if missed some)
extending the behaviour.
RealNumbers
cannot do any extra operations complex number can't do, so no point in doing this.implementing abstract behaviour with a specific implementation. Since
ComplexNumber
should not be abstract this also does not apply.code reuse. If you just use the
ComplexNumber
class you reuse 100% of the code.more specific/efficient/accurate implementation for a specific task. This could be applied here,
RealNumbers
could implement some functionalities faster. But then this subclass should be hidden behind the staticfromDouble(double)
and should not be known outside. This way it would not need to hide the imaginary part. For the outside there should only be complex numbers (which real numbers are). You could also return this private RealNumber class from any operations in the complex number class that results in a real number. (This assumes the classes are immutable as most number classes.)
It is like implementing a subclass of Integer that is called Zero and hardcode some of the operations since they are trivial for zero. You could do this, as every zero is an integer, but don't make it public, hide it behind a factory method.
I am not surprised to get some downvote, since I have no source to prove. Also if nobody else had an idea, I always suspect there might be some reason for that. But please tell me why you think it is wrong and how you would make it better.
– findusl
Jan 10 at 9:06
add a comment |
Solution: Do not have a public RealNumber
class
I would find it totally OK if ComplexNumber
had a static factory method fromDouble(double)
that would return a complex number with imaginary being zero. You can then use all the operations that you would use on a RealNumber
instance on this ComplexNumber
instance.
But I have trouble seeing why you would want/need to have a public inherited RealNumber
class. Usually inheritance is used for these reasons (out of my head, correct me if missed some)
extending the behaviour.
RealNumbers
cannot do any extra operations complex number can't do, so no point in doing this.implementing abstract behaviour with a specific implementation. Since
ComplexNumber
should not be abstract this also does not apply.code reuse. If you just use the
ComplexNumber
class you reuse 100% of the code.more specific/efficient/accurate implementation for a specific task. This could be applied here,
RealNumbers
could implement some functionalities faster. But then this subclass should be hidden behind the staticfromDouble(double)
and should not be known outside. This way it would not need to hide the imaginary part. For the outside there should only be complex numbers (which real numbers are). You could also return this private RealNumber class from any operations in the complex number class that results in a real number. (This assumes the classes are immutable as most number classes.)
It is like implementing a subclass of Integer that is called Zero and hardcode some of the operations since they are trivial for zero. You could do this, as every zero is an integer, but don't make it public, hide it behind a factory method.
Solution: Do not have a public RealNumber
class
I would find it totally OK if ComplexNumber
had a static factory method fromDouble(double)
that would return a complex number with imaginary being zero. You can then use all the operations that you would use on a RealNumber
instance on this ComplexNumber
instance.
But I have trouble seeing why you would want/need to have a public inherited RealNumber
class. Usually inheritance is used for these reasons (out of my head, correct me if missed some)
extending the behaviour.
RealNumbers
cannot do any extra operations complex number can't do, so no point in doing this.implementing abstract behaviour with a specific implementation. Since
ComplexNumber
should not be abstract this also does not apply.code reuse. If you just use the
ComplexNumber
class you reuse 100% of the code.more specific/efficient/accurate implementation for a specific task. This could be applied here,
RealNumbers
could implement some functionalities faster. But then this subclass should be hidden behind the staticfromDouble(double)
and should not be known outside. This way it would not need to hide the imaginary part. For the outside there should only be complex numbers (which real numbers are). You could also return this private RealNumber class from any operations in the complex number class that results in a real number. (This assumes the classes are immutable as most number classes.)
It is like implementing a subclass of Integer that is called Zero and hardcode some of the operations since they are trivial for zero. You could do this, as every zero is an integer, but don't make it public, hide it behind a factory method.
edited Jan 9 at 19:21
answered Jan 9 at 18:39
finduslfindusl
1275
1275
I am not surprised to get some downvote, since I have no source to prove. Also if nobody else had an idea, I always suspect there might be some reason for that. But please tell me why you think it is wrong and how you would make it better.
– findusl
Jan 10 at 9:06
add a comment |
I am not surprised to get some downvote, since I have no source to prove. Also if nobody else had an idea, I always suspect there might be some reason for that. But please tell me why you think it is wrong and how you would make it better.
– findusl
Jan 10 at 9:06
I am not surprised to get some downvote, since I have no source to prove. Also if nobody else had an idea, I always suspect there might be some reason for that. But please tell me why you think it is wrong and how you would make it better.
– findusl
Jan 10 at 9:06
I am not surprised to get some downvote, since I have no source to prove. Also if nobody else had an idea, I always suspect there might be some reason for that. But please tell me why you think it is wrong and how you would make it better.
– findusl
Jan 10 at 9:06
add a comment |
Saying that a real number is a complex number has more meaning in mathematics, especially set theory, than computer science.
In mathematics we say :
- A real number is a complex number because the set of complex numbers
includes the set of real numbers. - A rational number is a real number because the set of real numbers includes the set of rational numbers (and the set of
irrational numbers). - An integer is a rational number because the set of rational numbers includes the set of integers.
However, this does not mean you must, or even should, use inheritance when designing your library to include a RealNumber and ComplexNumber class. In Effective Java, Second Edition by Joshua Bloch; Item 16 is "Favor Composition Over Inheritance". To avoid the problems mentioned in that item, once you have your RealNumber class defined, it can be used in your ComplexNumber class:
public class ComplexNumber
private RealNumber realPart;
private RealNumber imaginaryPart;
// Implementation details are for you to write
This allows you all the power of reusing your RealNumber class to keep your code DRY while avoiding the issues identified by Joshua Bloch.
add a comment |
Saying that a real number is a complex number has more meaning in mathematics, especially set theory, than computer science.
In mathematics we say :
- A real number is a complex number because the set of complex numbers
includes the set of real numbers. - A rational number is a real number because the set of real numbers includes the set of rational numbers (and the set of
irrational numbers). - An integer is a rational number because the set of rational numbers includes the set of integers.
However, this does not mean you must, or even should, use inheritance when designing your library to include a RealNumber and ComplexNumber class. In Effective Java, Second Edition by Joshua Bloch; Item 16 is "Favor Composition Over Inheritance". To avoid the problems mentioned in that item, once you have your RealNumber class defined, it can be used in your ComplexNumber class:
public class ComplexNumber
private RealNumber realPart;
private RealNumber imaginaryPart;
// Implementation details are for you to write
This allows you all the power of reusing your RealNumber class to keep your code DRY while avoiding the issues identified by Joshua Bloch.
add a comment |
Saying that a real number is a complex number has more meaning in mathematics, especially set theory, than computer science.
In mathematics we say :
- A real number is a complex number because the set of complex numbers
includes the set of real numbers. - A rational number is a real number because the set of real numbers includes the set of rational numbers (and the set of
irrational numbers). - An integer is a rational number because the set of rational numbers includes the set of integers.
However, this does not mean you must, or even should, use inheritance when designing your library to include a RealNumber and ComplexNumber class. In Effective Java, Second Edition by Joshua Bloch; Item 16 is "Favor Composition Over Inheritance". To avoid the problems mentioned in that item, once you have your RealNumber class defined, it can be used in your ComplexNumber class:
public class ComplexNumber
private RealNumber realPart;
private RealNumber imaginaryPart;
// Implementation details are for you to write
This allows you all the power of reusing your RealNumber class to keep your code DRY while avoiding the issues identified by Joshua Bloch.
Saying that a real number is a complex number has more meaning in mathematics, especially set theory, than computer science.
In mathematics we say :
- A real number is a complex number because the set of complex numbers
includes the set of real numbers. - A rational number is a real number because the set of real numbers includes the set of rational numbers (and the set of
irrational numbers). - An integer is a rational number because the set of rational numbers includes the set of integers.
However, this does not mean you must, or even should, use inheritance when designing your library to include a RealNumber and ComplexNumber class. In Effective Java, Second Edition by Joshua Bloch; Item 16 is "Favor Composition Over Inheritance". To avoid the problems mentioned in that item, once you have your RealNumber class defined, it can be used in your ComplexNumber class:
public class ComplexNumber
private RealNumber realPart;
private RealNumber imaginaryPart;
// Implementation details are for you to write
This allows you all the power of reusing your RealNumber class to keep your code DRY while avoiding the issues identified by Joshua Bloch.
answered Jan 9 at 20:07
Craig NoahCraig Noah
195
195
add a comment |
add a comment |
There are two issues here. The first is that it's common to use the same terms for the types of containers and the types of their contents, especially with primitive types like numbers. The term double
, for example, is used to describe both a double-precision floating-point value and a container in which one may be stored.
The second issue is that while is-a relationships among containers from which various types of objects can be read behave the same as the relationships among the objects themselves, those among containers into which various types of objects can be placed behave opposite those among their contents. Every cage that's known to hold an instance of Cat
will be a cage that holds an instance of Animal
, but need not be be a cage that holds an instance of SiameseCat
. On the other hand, every cage that can hold all instances of Cat
will be a cage that can hold all instances of SiameseCat
, but need not be a cage that can hold all instances of Animal
. The only kind of cage that can hold all instances of Cat
and can be guaranteed never hold anything other than an instance of Cat
, is a cage of Cat
. Any other kind of cage would either be incapable of accepting some instances of Cat
that it should accept, or would be capable of accepting things that are not instances of Cat
.
add a comment |
There are two issues here. The first is that it's common to use the same terms for the types of containers and the types of their contents, especially with primitive types like numbers. The term double
, for example, is used to describe both a double-precision floating-point value and a container in which one may be stored.
The second issue is that while is-a relationships among containers from which various types of objects can be read behave the same as the relationships among the objects themselves, those among containers into which various types of objects can be placed behave opposite those among their contents. Every cage that's known to hold an instance of Cat
will be a cage that holds an instance of Animal
, but need not be be a cage that holds an instance of SiameseCat
. On the other hand, every cage that can hold all instances of Cat
will be a cage that can hold all instances of SiameseCat
, but need not be a cage that can hold all instances of Animal
. The only kind of cage that can hold all instances of Cat
and can be guaranteed never hold anything other than an instance of Cat
, is a cage of Cat
. Any other kind of cage would either be incapable of accepting some instances of Cat
that it should accept, or would be capable of accepting things that are not instances of Cat
.
add a comment |
There are two issues here. The first is that it's common to use the same terms for the types of containers and the types of their contents, especially with primitive types like numbers. The term double
, for example, is used to describe both a double-precision floating-point value and a container in which one may be stored.
The second issue is that while is-a relationships among containers from which various types of objects can be read behave the same as the relationships among the objects themselves, those among containers into which various types of objects can be placed behave opposite those among their contents. Every cage that's known to hold an instance of Cat
will be a cage that holds an instance of Animal
, but need not be be a cage that holds an instance of SiameseCat
. On the other hand, every cage that can hold all instances of Cat
will be a cage that can hold all instances of SiameseCat
, but need not be a cage that can hold all instances of Animal
. The only kind of cage that can hold all instances of Cat
and can be guaranteed never hold anything other than an instance of Cat
, is a cage of Cat
. Any other kind of cage would either be incapable of accepting some instances of Cat
that it should accept, or would be capable of accepting things that are not instances of Cat
.
There are two issues here. The first is that it's common to use the same terms for the types of containers and the types of their contents, especially with primitive types like numbers. The term double
, for example, is used to describe both a double-precision floating-point value and a container in which one may be stored.
The second issue is that while is-a relationships among containers from which various types of objects can be read behave the same as the relationships among the objects themselves, those among containers into which various types of objects can be placed behave opposite those among their contents. Every cage that's known to hold an instance of Cat
will be a cage that holds an instance of Animal
, but need not be be a cage that holds an instance of SiameseCat
. On the other hand, every cage that can hold all instances of Cat
will be a cage that can hold all instances of SiameseCat
, but need not be a cage that can hold all instances of Animal
. The only kind of cage that can hold all instances of Cat
and can be guaranteed never hold anything other than an instance of Cat
, is a cage of Cat
. Any other kind of cage would either be incapable of accepting some instances of Cat
that it should accept, or would be capable of accepting things that are not instances of Cat
.
answered Jan 9 at 22:35
supercatsupercat
6,9701726
6,9701726
add a comment |
add a comment |
Thanks for contributing an answer to Software Engineering Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f385185%2fhow-to-implement-realnumber-and-complexnumber-inheritance%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
7
this looks like covered in prior question: Should rectangle inherit from square?
– gnat
Jan 9 at 13:37
1
@gnat Oh man, that was another example I wanted to use... Thanks!
– Betlista
Jan 9 at 14:14
7
... Note that the sentence "real number is a complex number" in the mathematical sense is only valid for immutable numbers, so if you use immutable objects, you can avoid the LSP violation (same holds also for squares and rectangles, see this SO answer).
– Doc Brown
Jan 9 at 15:20
5
... Note further the absolute value calculation for complex numbers works also for real numbers, so I am not sure what your professor meant. If you implement an "Abs()" method correctly in an immutable complex number and derive a "real" from it, the Abs() method will still deliver correct results.
– Doc Brown
Jan 9 at 15:23
3
Possible duplicate of Should rectangle inherit from square?
– BobDalgleish
Jan 9 at 17:21