Abstract class VS Enumerations (general OOP) - oop

I really can't find how to decide which option is the best. I have a class "Product" which has a "RecommendedAge" for the animal intended to be fed, among other attributes.
Please note that I just want the different values from RecommendedAge for each species, I don't care about their numerical equivalent (what would be represented with a Discriminated Union, but I can't use that due to ORM issues).
As "RecommendedAge" possible values differ depending on the type of Animal de Product targets, I don't know which of the following (or any other) approach is the best (all pseudocode):
Class Product {
Id id;
String name;
RecommendedAge recommendedAge;
}
AbstractClass RecommendedAge {
}
Class DogRecommendedAge : RecommendedAge {
readonly const Int Big;
readonly const Int Small;
}
Class CatRecommendedAge : RecommendedAge {
readonly const Int Medium;
readonly const Int Tiny;
}
Or something like:
AbstractClass Product {
Id id;
String name;
}
Enum DogRecommendedAge {
Big = 0;
Small = 1;
}
Enum CatRecommendedAge {
Medium = 0;
Tiny= 1;
}
Class DogProduct : Product {
DogRecommendedAge dogRecommendedAge;
}
Class CatProduct : Product {
CatRecommendedAge catRecommendedAge;
}
This may be a very silly one, but I'm stuck. Thank you all.

What about just storing recommended ages during runtime instead of at compile time? In your pseudo:
class RecommendedAges {
readonly const RecommendedAge dog = new RecommendedAge(2, 5); // example value
readonly const RecommendedAge cat = new RecommendedAge(3, 4); // example value
}
Class Product {
Id id;
String name;
RecommendedAge recommendedAge;
}
Product p = new Product(1, 'dog food', RecommendedAges.dog);

Related

Can mixins access the state of the class they're mixed with in Dart?

Can mixins access the state of the class they're mixed with in Dart?
Yes, through the use of on key word. This example illustrates:
void main() {
final person = Bob();
print(person.age);
print(person.ageInside);
// output will be 31, 13
}
mixin Comedian on Person {
// no need to declare age variable here, it finds it through `on`
#override
int get ageInside {
return age - 18;
}
}
class Person {
int age;
int get ageInside {
return age;
}
Person(this.age);
}
class Bob extends Person with Comedian {
Bob() : super(31);
}

How to change values of variables using methods?

I am having troubles incrementing the value of my instance variables. I tried making a method so that for every pet I buy, it will add that much to how many I already have. But when I print dogs variable, it says 0 even though I added 2. I'd appreciate any help. Thanks!
public class myStuff
static int dogs;
static int cats;
public static void main(String[] args) {
myStuff.buy(dogs, 2);
System.out.println(dogs);
}
public static void buy(int pet, int howMany) {
pet = pet + howMany;
}
}
you cant do that in java, since it is pass-by-value
In Java, method parameters are passed by value (which means the value of dogsin your case is passed in the first Place, but never touched). Objects however, are manipulated by reference. So, if you want to increase the number of pets, you could use a class Pet with a value count
public class Pet {
private int count;
public Pet(int count) {
this.count = count;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
If you then pass an instance of Pet to your buy function and increase the count via setCount, the value will be saved.

Hibernate IndexEmbedded Spatial Entities

The Scenario
Class Employee, Class Office, Class OfficeEmployee.
Class office is a Spatial Entity, that can be searched and returns results as expected.
a manyToMany relationship between Office-Employee is mapped with the Class OfficeEmplyee.
Now I need to perform search based on certain people within some range. in other words I have to check for the offices in range and for emplyees who exist at those offices, i.e Searching the OfficeEmployee Entity.
All the three classes are indexed.
OfficeEmployee
// reference Spatial indexed entity Office
#IndexedEmbedded
#ManyToOne (cascade = CascadeType.MERGE)
#JoinColumn(name="office")
private Office office;
// reference to employee
#IndexedEmbedded
#JsonIgnore
#ManyToOne (cascade = CascadeType.MERGE)
#JoinColumn(name="employee")
private Employee employee;
Class Office
#JsonIgnoreProperties(ignoreUnknown=true)
#Spatial(name = "office_location_poi", spatialMode = SpatialMode.HASH )
#Indexed
#Entity
#Embeddable
public class Office implements Serializable,Coordinates {
// some attributes , getters , setters..
#ContainedIn
#OneToMany(mappedBy="office", cascade=CascadeType.ALL)
private List<OfficeEmployee > officeEmployees;
#Latitude
double latitude;
#Longitude
double longitude;
public Coordinates getLocation() {
return new Coordinates() {
#Override
public Double getLatitude() {
return latitude;
}
#Override
public Double getLongitude() {
return longitude;
}
};
}
#Override
public Double getLatitude() {
return latitude;
}
#Override
public Double getLongitude() {
return longitude;
}
}
The Query:
final QueryBuilder builder = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder().forEntity( OfficeEmployee.class ).get();
double centerLatitude = searchTerm.lat;
double centerLongitude =searchTerm.lng;
org.apache.lucene.search.Query luceneQuery = builder.spatial().onField("office").within(searchTerm.distance, Unit.KM)
.ofLatitude(centerLatitude)
.andLongitude(centerLongitude)
.createQuery();
org.hibernate.search.jpa.FullTextQuery hibQuery = fullTextEntityManager.createFullTextQuery(luceneQuery, OfficeEmployee.class);
// sort
Sort distanceSort = new Sort(
new DistanceSortField(centerLatitude, centerLongitude, "office_location_poi"));
hibQuery.setSort(distanceSort);
hibQuery.setProjection(FullTextQuery.SPATIAL_DISTANCE, FullTextQuery.THIS);
hibQuery.setFirstResult(0);
hibQuery.setMaxResults(20);
// results
List<Office>results =hibQuery.getResultList();
The Problem
Now I want to perform my search on the relationship table (OfficeEmployee).
but sounds like I can't get it to work! I checked tutorials, and couldn't find such an example.
Is it possible to use a currently indexed Entity like I have explained?
Do I have to include a #Spatial there in the OfficeEmployee ? but that will require a new indexing separately, I want to use the currently indexed one.
When I run search it says that I need to check #Spatial and #SpatialFieldBridge, and even if I annotate so, the results are empty.
In case that my Spatial entity was implementing the coordinates and doesn't have a separate field for coordinates, where should the #ContainedIn be placed ?
Can anyone please point me in the right direction ?

Why is this subclass' parent method call not polymorphic?

I've been dabbling in Dlang recently as C++ just wasn't quite sitting right with me after having used Python for so long. While dabbling, I came across what I thought would be a very simple exercise in polymorphism. I suppose how you would expect something to work and what it actually does are two entirely different things for reasons an end user probably can't comprehend. That being said, here is the source code of my "sandbox.D":
import std.stdio;
class Animal {
string voice = "--silence--";
void speak() {
writeln(this.voice);
}
}
class Dog : Animal {
string voice = "Whoof!";
}
int main() {
auto a = new Animal();
auto d = new Dog();
writeln(a.voice); // Prints "--silence--"
writeln(d.voice); // Prints "Whoof!"
a.speak(); // Prints "--silence--"
d.speak(); // Prints "--silence--" NOT "Whoof!"
return 0;
}
I guess my issue is why the "this" keyword just doesn't seem to be functioning how you would expect it to in the C++ successor language.
Methods are polymorphic, variables aren't. So instead of making the voice a variable, you want to override speak in the child.
Also, the auto return type doesn't work with polymorphism, you need to actually specify the types. (The reason is that auto return makes a function template in the compiler, which in theory could have multiple overridable slots in the function table, so it just doesn't try to put it in.)
So try this out:
import std.stdio;
class Animal {
void speak() { // changed to void instead of auto
writeln("--silence--");
}
}
class Dog : Animal {
override void speak() { // the override tells it to override the base method
writeln("woof");
}
}
int main() {
auto d = new Dog();
d.speak();
return 0;
}
If you have a lot of shared functionality and want to reuse one function with slight changes in child classes, you might make a method instead of a variable that just returns something.
Like string voice() { return "woof"; }, then it can be overridden in children.
Another way is to use template this parameter:
import std.stdio;
class Animal {
string voice;
void speak(this C)() {
writeln((cast(C)this).voice);
}
}
class Dog : Animal {
string voice = "Whoof!";
}
int main() {
auto a = new Animal();
auto d = new Dog();
a.speak(); // Prints ""
d.speak(); // Prints "Whoof!"
return 0;
}
Or when you do not need to have voice as a member:
import std.stdio;
class Animal {
static immutable voice = "";
void speak(this C)() {
writeln(C.voice);
}
}
class Dog : Animal {
static immutable voice = "Whoof!";
}
int main() {
auto a = new Animal();
auto d = new Dog();
a.speak(); // Prints ""
d.speak(); // Prints "Whoof!"
return 0;
}

Refactoring code using Strategy Pattern

I have a GiftCouponPayment class. It has a business strategy logic which can change frequently - GetCouponValue(). At present the logic is “The coupon value should be considered as zero when the Coupon Number is less than 2000”. In a future business strategy it may change as “The coupon value should be considered as zero when the Coupon Issued Date is less than 1/1/2000”. It can change to any such strategies based on the managing department of the company.
How can we refactor the GiftCouponPayment class using Strategy pattern so that the class need not be changed when the strategy for GetCouponValue method?
UPDATE: After analyzing the responsibilities, I feel, "GiftCoupon" will be a better name for "GiftCouponPayment" class.
C# CODE
public int GetCouponValue()
{
int effectiveValue = -1;
if (CouponNumber < 2000)
{
effectiveValue = 0;
}
else
{
effectiveValue = CouponValue;
}
return effectiveValue;
}
READING
Strategy Pattern - multiple return types/values
GiftCouponPayment class should pass GiftCoupon to different strategy classes. So your strategy interface (CouponValueStrategy) should contain a method:
int getCouponValue(GiftCoupon giftCoupon)
Since each Concrete strategy implementing CouponValueStrategy has access to GiftCoupon, each can implement an algorithm based on Coupon number or Coupon date etc.
You can inject a "coupon value policy" into the coupon object itself and call upon it to compute the coupon value. In such cases, it is acceptable to pass this into the policy so that the policy can ask the coupon for its required attributes (such as coupon number):
public interface ICouponValuePolicy
{
int ComputeCouponValue(GiftCouponPayment couponPayment);
}
public class GiftCouponPayment
{
public ICouponValuePolicy CouponValuePolicy {
get;
set;
}
public int GetCouponValue()
{
return CouponValuePolicy.ComputeCouponValue(this);
}
}
Also, it seems like your GiftCouponPayment is really responsible for two things (the payment and the gift coupon). It might make sense to extract a GiftCoupon class that contains CouponNumber, CouponValue and GetCouponValue(), and refer to this from the GiftCouponPayment.
When your business - logic changes, it's quite natural that your code will have to change as well.
You could perhaps opt to move the expiration-detection logic into a specification class:
public class CouponIsExpiredBasedOnNumber : ICouponIsExpiredSpecification
{
public bool IsExpired( Coupon c )
{
if( c.CouponNumber < 2000 )
return true;
else
return false;
}
}
public class CouponIsExpiredBasedOnDate : ICouponIsExpiredSpecification
{
public readonly DateTime expirationDate = new DateTime (2000, 1, 1);
public bool IsExpired( Coupon c )
{
if( c.Date < expirationDate )
return true;
else
return false;
}
}
public class Coupon
{
public int GetCouponValue()
{
ICouponIsExpiredSpecification expirationRule = GetExpirationRule();
if( expirationRule.IsExpired(this) )
return 0;
else
return this.Value;
}
}
The question you should ask yourself: is it necessary to make it this complex right now ? Can't you make it as simple as possible to satisfy current needs, and refactor it later, when the expiration-rule indeed changes ?
The behavior that you wish to be dynamic is the coupon calculation - which can dependent on any number of things: coupon date, coupon number, etc. I think that a provider pattern would be more appropriate, to inject a service class which calculates the coupon value.
The essence of this is moving the business logic outside of the GiftCouponPayment class, and using a class I'll call "CouponCalculator" to encapsulate the business logic. This class uses an interface.
interface ICouponCalculator
{
int Calculate (GiftCouponPayment payment);
}
public class CouponCalculator : ICouponCalculator
{
public int Calculate (GiftCouponPayment payment)
{
if (payment.CouponNumber < 2000)
{
return 0;
}
else
{
return payment.CouponValue;
}
}
}
Now that you have this interface and class, add a property to the GiftCouponPayment class, then modify your original GetCouponValue() method:
public class GiftCouponPayment
{
public int CouponNumber;
public int CouponValue;
public ICouponCalculator Calculator { get; set; }
public int GetCouponValue()
{
return Calculator.Calculate(this);
}
}
When you construct the GiftCouponPayment class, you will assign the Calculator property:
var payment = new GiftCouponPayment() { Calculator = new CouponCalculator(); }
var val = payment.GetCouponValue(); // uses CouponCalculator class to get value
If this seems like a lot of work just to move the calculation logic outside of the GiftCouponPayment class, well, it is! But if this is your requirement, it does provide several things:
1. You won't need to change the GiftCouponPayment class to adjust the calculation logic.
2. You could create additional classes that implement ICalculator, and a factory pattern to decide which class to inject into GiftCouponPayment when it is constructed. This speaks more to your original desire for a "strategy" pattern - as this would be useful if the logic becomes very complex.