Javascript
Can setter used to validate parameter when creating new object, as seen on this code, the string input on numberOfStudents bypass the setter
class School {
constructor(name, level, numberOfStudents) {
this._name = name;
this._level = level;
this._numberOfStudents = numberOfStudents;
}
get numberOfStudents() {
return this._numberOfStudents;
}
set numberOfStudents(value) {
if (isNaN(value)) {
console.log('Invalid input: numberOfStudents must be set to a Number.');
} else {
return (this._numberOfStudents = value);
}
}
}
const primaryOne = new School('Primary One', 'L1', 'ten');
prints
School { _name: 'Primary One', _level: 'L1', _numberOfStudents: 'ten' }
Please help
You're bypassing the validation because you're assigning to the internal _numberOfStudents property. The setter is only run when you assign to numberOfStudents. So change the constructor to do that:
class School {
constructor(name, level, numberOfStudents) {
this._name = name;
this._level = level;
this.numberOfStudents = numberOfStudents;
}
get numberOfStudents() {
return this._numberOfStudents;
}
set numberOfStudents(value) {
if (isNaN(value)) {
console.log('Invalid input: numberOfStudents must be set to a Number.');
} else {
this._numberOfStudents = value;
}
}
}
const primaryOne = new School('Primary One', 'L1', 'ten');
help me out in deleting particular relation
Person=Alex Relation=Brothers
Expected Output should be
Brothers=John,Joe
Husband=Bern Wife=Julia
The application should add Julia as a spouse for Bern.
now i want to delete the relation between Bern and wife julia and i am not able to do
Person=Bern Relation=Wife
Should return output as:
Wife=Julia
$ run_application
Input: Husband=Bern Wife=Julia
Output: Welcome to the family, Julia!
Input: Person=Bern Relation=Wife
Output: Wife=Julia
import java.util.*;
import java.util.stream.Collectors;
class Person {
private String name;
private Gender gender;
private List<Relation> relations = new ArrayList<>();
Person(String name, Gender gender) {
this.name = name;
this.gender = gender;
}
public String getName() {
return name;
}
public List<Relation> getRelations() {
return relations;
}
public Gender getGender() {
return gender;
}
public void addRelation(Relation relation) {
relations.add(relation);
}
public void deleteRelation(Relation relation) {
relations.remove(relation);
}
}
class Relation {
private TreeRelationType type;
private Person person1;
private Person person2;
Relation(TreeRelationType type, Person person1, Person person2) {
this.type = type;
this.person1 = person1;
this.person2 = person2;
}
public TreeRelationType getType() {
return type;
}
public Person getPerson2() {
return person2;
}
}
enum TreeRelationType {
SPOUSE, PARENT, CHILD
}
enum Gender {
MALE, FEMALE
}
enum RelationType {
FATHER, MOTHER, BROTHER, SON,GRANDCHILDREN, DAUGHTER, AUNT, HUSBAND, WIFE
}
class InvalidInputException extends Exception {
static final long serialVersionUID = -3387516993334229948L;
public InvalidInputException(String message) {
super(message);
}
}
public class FamilyTree {
private Person root;
private Map<String, Boolean> visted = new HashMap<>();
private Gender fetchGender(RelationType type) {
if(RelationType.MOTHER.equals(type)||RelationType.DAUGHTER.equals(type)|| RelationType.WIFE.equals(type))
return Gender.FEMALE;
else
return Gender.MALE;
}
private TreeRelationType fetchTreeRelationType(RelationType type) {
if (RelationType.MOTHER.equals(type) || RelationType.FATHER.equals(type))
return TreeRelationType.CHILD;
else if (RelationType.HUSBAND.equals(type) || RelationType.WIFE.equals(type))
return TreeRelationType.SPOUSE;
else
return TreeRelationType.PARENT;
}
public void addPerson(String name1, RelationType type1, String name2, RelationType type2)
throws InvalidInputException {
TreeRelationType relationType1 = fetchTreeRelationType(type1);
TreeRelationType relationType2 = fetchTreeRelationType(type2);
Gender gender1 = fetchGender(type1);
Gender gender2 = fetchGender(type2);
if (this.root == null) {
Person person1 = new Person(name1, gender1);
Person person2 = new Person(name2, gender2);
this.root = person1;
addRelation(relationType1, person1, relationType2, person2);
} else {
Person person1 = findPerson(this.root, name1);
if (person1 == null) {
throw new InvalidInputException("Invalid Input");
}
Person person2 = new Person(name2, gender2);
addRelation(relationType1, person1, relationType2, person2);
if (TreeRelationType.CHILD.equals(relationType1)) {
for (Relation relation : person1.getRelations()) {
if (TreeRelationType.SPOUSE.equals(relation.getType())) {
person1 = relation.getPerson2();
break;
}
}
deleteRelation(relationType1, person1, relationType2, person2);
}
}
}
public void deleteperson(String name1, RelationType type1, String name2, RelationType type2)
throws InvalidInputException {
TreeRelationType relationType1 = fetchTreeRelationType(type1);
TreeRelationType relationType2 = fetchTreeRelationType(type2);
Gender gender1 = fetchGender(type1);
Gender gender2 = fetchGender(type2);
Person person1 = findPerson(this.root, name1);
if (person1 == null) {
throw new InvalidInputException("Invalid Input");
}
Person person2 = findPerson(this.root, name2);
if (person2 == null) {
throw new InvalidInputException("Invalid Input");
}
deleteRelation(relationType1, person1, relationType2, person2);
if (TreeRelationType.CHILD.equals(relationType1)) {
for (Relation relation : person1.getRelations()) {
if (TreeRelationType.SPOUSE.equals(relation.getType())) {
person1 = relation.getPerson2();
break;
}
}
addRelation(relationType1, person1, relationType2, person2);
}
}
private Person findPerson(Person cur, String name) {
this.visted.put(cur.getName(), Boolean.TRUE);
if (cur.getName().equals(name)) {
this.visted.clear();
return cur;
} else {
for (Relation relation : cur.getRelations()) {
Person person2 = relation.getPerson2();
if (!visted.containsKey(person2.getName())) {
Person person = findPerson(person2, name);
if (person != null) {
return person;
}
}
}
}
return null;
}
private void addRelation(TreeRelationType type1, Person person1, TreeRelationType type2, Person person2) {
Relation relation1 = new Relation(type1, person1, person2);
person1.addRelation(relation1);
Relation relation2 = new Relation(type2, person2, person1);
person2.addRelation(relation2);
}
private void deleteRelation(TreeRelationType type1, Person person1, TreeRelationType type2, Person person2) {
Relation relation1 = new Relation(type1, person1, person2);
person1.deleteRelation(relation1);
Relation relation2 = new Relation(type2, person2, person1);
person2.deleteRelation(relation2);
}
private List<Person> fetchChildren(String name) throws InvalidInputException {
List<Person> children = new ArrayList<>();
Person person = findPerson(this.root, name);
if (person == null) {
throw new InvalidInputException("Invalid Input");
}
for (Relation relation : person.getRelations()) {
if (TreeRelationType.CHILD.equals(relation.getType())) {
children.add(relation.getPerson2());
}
}
return children;
}
private List<Person> fetchParents(String name) throws InvalidInputException {
List<Person> parents = new ArrayList<>();
Person person = findPerson(this.root, name);
if (person == null) {
throw new InvalidInputException("Invalid Input");
}
for (Relation relation : person.getRelations()) {
if (TreeRelationType.PARENT.equals(relation.getType())) {
parents.add(relation.getPerson2());
}
}
return parents;
}
private Person fetchFather(String name) throws InvalidInputException {
Person father = null;
List<Person> parents = fetchParents(name);
for (Person person : parents) {
if (Gender.MALE.equals(person.getGender()))
father = person;
}
return father;
}
private Person fetchMother(String name) throws InvalidInputException {
Person mother = null;
List<Person> parents = fetchParents(name);
for (Person person : parents) {
if (Gender.FEMALE.equals(person.getGender()))
mother = person;
}
return mother;
}
private List<Person> fetchSiblings(String name) throws InvalidInputException {
List<Person> siblings = new ArrayList<>();
Person father = fetchFather(name);
if (father != null) {
List<Person> children = fetchChildren(father.getName());
for (Person person : children) {
if (!person.getName().equals(name)) {
siblings.add(person);
}
}
}
return siblings;
}
private List<Person> fetchBrothers(String name) throws InvalidInputException {
List<Person> brothers = new ArrayList<>();
List<Person> siblings = fetchSiblings(name);
for (Person person : siblings) {
if (Gender.MALE.equals(person.getGender())) {
brothers.add(person);
}
}
return brothers;
}
private List<Person> fetchGrandChildren(String name) throws InvalidInputException {
List<Person> children = fetchChildren(name);
List<Person> grandChildren = new ArrayList<>();
for (Person person : children) {
grandChildren.addAll(fetchChildren(person.getName()));
}
return grandChildren;
}
private List<Person> fetchAunts(String name) throws InvalidInputException {
List<Person> aunts = new ArrayList<>();
List<Person> parents = fetchParents(name);
for (Person person : parents) {
List<Person> siblings = fetchSiblings(person.getName());
for (Person sibling : siblings) {
if (Gender.FEMALE.equals(sibling.getGender())) {
aunts.add(sibling);
} else {
Optional<Person> spouce = Optional.ofNullable(fetchSpouce(sibling.getName()));
if (spouce.isPresent()) {
aunts.add(spouce.get());
}
}
}
}
return aunts;
}
private Person fetchSpouce(String name) throws InvalidInputException {
Person spouce = null;
Person person = findPerson(this.root, name);
if (person == null) {
throw new InvalidInputException("Invalid Input");
}
for (Relation relation : person.getRelations()) {
if (TreeRelationType.SPOUSE.equals(relation.getType())) {
spouce = relation.getPerson2();
break;
}
}
return spouce;
}
public static void main(String args[]) throws InvalidInputException {
FamilyTree tree = new FamilyTree();
tree.addPerson("Dilshada", RelationType.MOTHER, "Laraib", RelationType.SON);
tree.addPerson("Dilshada", RelationType.WIFE, "Mushtaq", RelationType.HUSBAND);
tree.addPerson("Dilshada", RelationType.MOTHER, "Laieba", RelationType.DAUGHTER);
tree.addPerson("Mushtaq", RelationType.FATHER, "Farheen", RelationType.DAUGHTER);
tree.addPerson("Mushtaq", RelationType.BROTHER, "Ashraf", RelationType.BROTHER);
tree.addPerson("Ashraf", RelationType.HUSBAND, "Kulsum", RelationType.WIFE);
tree.addPerson("Mushtaq", RelationType.SON, "Nani", RelationType.MOTHER);
Scanner sc = new Scanner(System.in);
int choice;
do{
System.out.println("1. Add Relation\n2. View Relation\n3. Delete Relation\n4. Exit\n");
System.out.println("Enter Your Choice");
choice = sc.nextInt();
switch (choice) {
case 1:
try {
System.out.println("Enter The {name1}={relationtype1} {name2}={relationtype2}");
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
String inputString = sc.nextLine();
if (!inputString.isEmpty()) {
String[] input = inputString.split(" ");
String name1 = input[0].split("=")[1];
String name2 = input[1].split("=")[1];
RelationType type1 = RelationType.valueOf(input[0].split("=")[0].toUpperCase());
RelationType type2 = RelationType.valueOf(input[1].split("=")[0].toUpperCase());
tree.addPerson(name1, type1, name2, type2);
System.out.println("Welcome to the family, " + name2 + "!");
}
} catch (Exception ex) {
ex.printStackTrace();
}
break;
case 2:
try {
System.out.println("Enter The {name} {relationtype}");
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
String inputString = sc.nextLine();
System.out.println(inputString);
if (!inputString.isEmpty()) {
String[] input = inputString.split(" ");
String relation = input[1];
String name = input[0];
String value = relation.toUpperCase();
if (value.charAt(value.length() - 1) == 'S') {
value = value.substring(0, value.length() - 1);
}
RelationType relationType = RelationType.valueOf(value);
switch (relationType) {
case FATHER:
Optional<Person> father = Optional.ofNullable(tree.fetchFather(name));
if (father.isPresent()) {
System.out.println(relation + "=" + tree.fetchFather(name).getName());
}
break;
case MOTHER:
Optional<Person> mother = Optional.ofNullable(tree.fetchMother(name));
if (mother.isPresent()) {
System.out.println(relation + "=" + tree.fetchMother(name).getName());
}
break;
case BROTHER:
System.out.println(relation + "=" + tree.fetchBrothers(name).stream()
.map(Person::getName).collect(Collectors.joining(",")));
break;
case GRANDCHILDREN:
System.out.println(relation + "=" + tree.fetchGrandChildren(name).stream()
.map(Person::getName).collect(Collectors.joining(",")));
break;
case AUNT:
System.out.println(relation + "=" + tree.fetchAunts(name).stream().map(Person::getName)
.collect(Collectors.joining(",")));
break;
case WIFE:
Optional<Person> spouce = Optional.ofNullable(tree.fetchSpouce(name));
if (spouce.isPresent()) {
System.out.println(relation + "=" + tree.fetchSpouce(name).getName());
}
break;
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
break;
case 3:
try {
System.out.println("Enter The {name1}={relationtype1} {name2}={relationtype2}");
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
String inputString = sc.nextLine();
if (!inputString.isEmpty()) {
String[] input = inputString.split(" ");
String name1 = input[0].split("=")[1];
String name2 = input[1].split("=")[1];
RelationType type1 = RelationType.valueOf(input[0].split("=")[0].toUpperCase());
RelationType type2 = RelationType.valueOf(input[1].split("=")[0].toUpperCase());
System.out.println(name1 +" "+name2+" "+type1+" "+type2);
tree.deleteperson(name1, type1, name2, type2);
System.out.println("Deleted from the family, " + name2 + "!");
}
} catch (Exception ex) {
ex.printStackTrace();
}
break;
case 4:
System.out.println("Existing");
break;
}
}while(choice !=4);
}
}
help me in correcting case 3 in main method of deleting relation
I'm trying to create a factory for instantiating my classes with generics. Checked out TypeScript docs and it all works perfectly. In short, this works just fine:
class Person {
firstName = 'John';
lastName = 'Doe';
}
class Factory {
create<T>(type: (new () => T)): T {
return new type();
}
}
let factory = new Factory();
let person = factory.create(Person);
console.log(JSON.stringify(person));
Now define class Person in directory:
export class Person extends BasePerson {
firstName = 'John';
lastName = 'Doe';
}
And when I import Person from other package:
import { Person } from "./directory"
class Factory {
create<T>(type: (new () => T)): T {
return new type();
}
}
let factory = new Factory();
let person = factory.create(Person);
I get error:
Argument of type 'typeof Person' is not assignable to parameter of type 'new () => Person'
How can I get a value of Person instead of typeof Person?
Using TypeScript 3.7.2 and Node v10.13.0.
Could you try this for me please?
import { Person } from "./directory"
class Factory {
create<T>(type: (new () => T)): T {
return new type();
}
}
let factory = new Factory();
let person = factory.create(new Person);
Actual problem here was a parent class of Person -> BasePerson. BasePerson expected an argument in its constructor, so when I tried to call factory.create(Person), Person actually was an typeof because it expected an argument for base class constructor. Problem was solved by deleting the constructor in base class and injecting a property via ioc container, in my case Inversify.
class Vehicle {
constructor (name, type) {
this.name = name;
this.type = type;
console.log(this.constructor.name);
}
getName () {
return this.name;
}
getType () {
return this.type;
}
static create(name, type) {
return new Vehicle(name, type);
}
}
class Car extends Vehicle {
constructor (name) {
super(name, 'car');
}
getName () {
return 'It is a car: ' + super.getName();
}
}
let car = Car.create('Tesla', 'car');
console.log(car.getName()); // It is a car: Tesla
console.log(car.getType()); // car
The above code use ES6 class keyword to define a Vehicle class and a subclass Car from it. How to return Car instance from Vehicle static method.
Try:
let car = new Car('Tesla')
You can pass the ClassName you want to use within your static function create and create an instance from it.
static create(name, type, objClass) {
return new Function(`return new ${objClass ? objClass : 'Vehicle'}('${name}', '${type}');`)();
}
The Function class receives a String with the expression to evaluate, in your case:
new Function(`return new ${objClass}('${name}', '${type}');`)()
Look at this code
class Vehicle {
constructor(name, type) {
this.name = name;
this.type = type;
}
getName() {
return this.name;
}
getType() {
return this.type;
}
static create(name, type, objClass) {
return new Function(`return new ${objClass ? objClass : 'Vehicle'}('${name}', '${type}');`)();
}
}
class Car extends Vehicle {
constructor(name) {
super(name, 'car');
}
getName() {
return 'It is a car: ' + super.getName();
}
}
let car = Car.create('Tesla', 'car', 'Car');
console.log(car.getName()); // It is a car: Tesla
console.log(car.getType()); // car
let superCar = Vehicle.create('Tesla', 'car');
console.log(superCar.getName()); // Tesla
console.log(superCar.getType()); // car
.as-console-wrapper {
max-height: 100% !important
}
See? now is printing the right output.
Resources
Class Function
I want to track changes to the properties of my classes in typescript so that I only update the fields in my database which have actually changed. Currently, I am using an array where I add properties when they change and then I iterate through the array to determine what fields changed and need to be updated in the database. However, I would prefer to do this with some sort of isDirty check. My thought is that I would be able to call something like if (property.dirty) then {} to determine if a property has changed.
I remember being able to do something along these lines in vb.net, but it's been a while and I can't remember exactly what we did in that codebase.
Is the desired code below possible?
Current Code
class test{
private _ID: Guid;
private _dirty: Array<{}>;
get ID(): Guid {
return this._ID;
}
set ID(id: Guid) {
if (this._ID != id) {
this._ID = id;
this._dirty.filter(function (f) { return f.Field == "id" }).length > 0 ? this._dirty.filter(function (f) { return f.Field == "id" })[0].Value = id.toString() : this._dirty.push({Field: "id", Value: id});
}
}
get Name(): string {
return this._Name;
}
set Name(name: string) {
if (this._Name != name) {
this._Name = name;
this._DirtyFields.filter(function (f) { return f.Field == "ccseq_name" }).length > 0 ? this._DirtyFields.filter(function (f) { return f.Field == "ccseq_name" })[0].Value = name : this._DirtyFields.push(new EntityField("ccseq_name", name, FieldType.String));
}
}
}
Desired Code
class test{
private _ID: Guid;
get ID(): Guid {
return this._ID;
}
set ID(id: Guid) {
if (this._ID != id) {
this._ID = id;
this._ID.isDirty = true;
}
}
get Name(): string {
return this._Name;
}
set Name(name: string) {
if (this._Name != name) {
this._Name = name;
this._Name.isDirty = true;
}
}
}
In javascript you can add a property to an object so it's not a problem to do this:
this._ID.dirty = true;
Even when Guid doesn't have this dirty member.
The problem of course is typescript which will complain because of that.
To avoid that you can simply do:
private _ID: Guid & { dirty?: boolean };
Edit
Again, javascript already supports it, you can do this:
obj.dirty = true;
For any js type: booleans, strings, arrays and even functions.
But for having support for that in typescript you can do this:
interface Object {
dirty?: boolean;
}
But be aware that you are adding this to **all* of the objects that you have in your code. As you're not actually changing the prototype it won't have any effect in runtime, but typescript-wise it will effect all instances.
The way I solved this was to create a Field class that I then used as properties in my Objects.
Field Class
export class EntityField {
private _Field: string;
private _Value: any;
private _FType: FieldType;
private _isDirty: boolean;
constructor(field: string, value: any, fType: FieldType) {
this._Field = field;
this._Value = value;
this._FType = fType;
this._isDirty = false;
}
markClean(): void {
this._isDirty = false;
}
markDirty(): void {
this._isDirty = true;
}
get isDirty(): boolean {
return this._isDirty;
}
get Field(): string {
return this._Field;
}
set Field(field) {
if (this._Field !== field) {
this._Field = field;
}
}
get Value(): any {
return this._Value;
}
set Value(value: any) {
if (this._Value !== value) {
this._Value = value;
this._isDirty = true;
}
}
get FType(): FieldType {
return this._FType;
}
set FType(fType: FieldType) {
if (this._FType != fType) {
this._FType = fType;
}
}
}
Usage
export class Entity{
public Name: Field
}
Entity test = new Entity()
Entity.Name.isDirty() // Returns False
Entity.Name.Value = "Test";
Entity.Name.isDirty() // Returns True